我在给JTable单元着色时遇到麻烦。我正在做俄罗斯方块游戏。游戏的所有功能均有效;按下按钮,键盘交互来移动片段,移除完整的行等。现在发生的输出就是简单地打印出表格整数值(请参见屏幕截图)。这些整数值表示颜色。我有代码根据下面的MyRenderer类中的所述整数值更改单元格的颜色,但是没有着色。我想知道是否有一些我找不到的“渲染”方法,还是需要建立自己的绘画方法来调用?
有什么建议么?
startGame.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
card3.remove(0); // Removes button
model = new MyTableModel();
table = new JTable(model);
table.setDefaultRenderer(int.class, new MyRenderer());
table.setRowHeight(GRID_ROW_HEIGHT);
table.setFocusable(false);
table.setRowSelectionAllowed(true);
for (int i = 0; i < NUM_COLS; i++) {
table.getColumnModel().getColumn(i)
.setPreferredWidth(table.getRowHeight());
}
card3.add(table);
JButton pauseButton = new JButton("Pause");
card3.add(pauseButton);
pauseButton.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
game.pause();
}
});
card3.setFocusable(true);
card3.requestFocusInWindow();
KeyListener kl = new KeyListener() {
public void keyTyped(KeyEvent e) {
}
public void keyReleased(KeyEvent e) {
}
@Override
public void keyPressed(KeyEvent e) {
if (e.getKeyChar() == 'a' || e.getKeyChar() == 'A') {
game.move_Left();
draw_grid_first_time();
card3.revalidate();
} else if (e.getKeyChar() == 'd'
|| e.getKeyChar() == 'D') {
game.move_Right();
draw_grid_first_time();
card3.revalidate();
} else if (e.getKeyChar() == 'q'
|| e.getKeyChar() == 'Q') {
game.rotate_left();
draw_grid_first_time();
card3.revalidate();
} else if (e.getKeyChar() == 'e'
|| e.getKeyChar() == 'E') {
game.rotate_right();
draw_grid_first_time();
card3.revalidate();
} else if (e.getKeyChar() == ' ') {
game.pause();
}
}
};
card3.addKeyListener(kl);
draw_grid_first_time();
card3.revalidate(); // Redraws graphics
Timer timer = new Timer(500, new ActionListener() {
@Override
public void actionPerformed(ActionEvent arg0) {
if (!game.getPause()) {
game.move_Down();
draw_grid();
card3.revalidate(); // Redraws graphics
}
}
public void draw_grid() {
for (int i = 0; i < game.getNumRows(); i++) {
for (int j = 0; j < game.getNumCols(); j++) {
int[][] grid = game.getGrid();
model.setValueAt(grid[j][i], i, j);
}
}
}
});
timer.setRepeats(true);
timer.setCoalesce(true);
timer.start();
if (game.isOver()) {
timer.stop();
}
}
});
// Sets up layout
cards = new JPanel(new CardLayout());
cards.add(card1, SPLASHSCREEN);
cards.add(card2, MAINMENU);
cards.add(card3, TETRIS);
// Creates the actual window
pane.add(cards, BorderLayout.CENTER);
}
public void draw_grid_first_time() {
for (int i = 0; i < game.getNumRows(); i++) {
for (int j = 0; j < game.getNumCols(); j++) {
int[][] grid = game.getGrid();
model.setValueAt(grid[j][i], i, j);
}
}
}
// Render each cell as a background color dependent on grid from tetris game
class MyRenderer implements TableCellRenderer {
public Component getTableCellRendererComponent(JTable table,
Object value, boolean isSelected, boolean hasFocus, int row,
int column) {
JTextField editor = new JTextField();
if (value != null) {
editor.setText(value.toString());
}
if ((Integer) table.getValueAt(row, column) == 0) {
editor.setBackground(Color.DARK_GRAY);
} else if ((Integer) table.getValueAt(row, column) == 1) {
editor.setBackground(Color.RED);
} else if ((Integer) table.getValueAt(row, column) == 2) {
editor.setBackground(Color.GREEN);
} else if ((Integer) table.getValueAt(row, column) == 3) {
editor.setBackground(Color.BLUE);
} else if ((Integer) table.getValueAt(row, column) == 4) {
editor.setBackground(Color.YELLOW);
}
return editor;
}
}
// Overwrite the Table Model to be what I want color wise
@SuppressWarnings("serial")
class MyTableModel extends AbstractTableModel {
private int[][] values = new int[NUM_COLS][NUM_ROWS];
public int getColumnCount() {
return NUM_COLS;
}
public int getRowCount() {
return NUM_ROWS;
}
public Object getValueAt(int row, int col) {
return values[col][row];
}
public void setValueAt(Object val, int row, int col) {
values[col][19 - row] = (Integer) val;
fireTableCellUpdated(row, col);
}
}
最佳答案
您不应在渲染器的getTableCellRendererComponent()
中分配新组件。 JTable
对所有单元格重复使用单个渲染器。在您的情况下,您会为每个单元多次分配新组件。有关详细信息,请参见“如何使用表”教程中的Concepts: Editors and Renderers。考虑DefaultTableCellRenderer
的扩展(请注意,DefaultTableCellRenderer
是JLabel
的扩展):
class MyRenderer extends DefaultTableCellRenderer {
public Component getTableCellRendererComponent(JTable table,
Object value, boolean isSelected, boolean hasFocus, int row,
int column) {
Component c = super.getTableCellRendererComponent(table,
value, isSelected, hasFocus, row, column);
c.setBackground(getColor((Integer) value));
return c;
}
private Color getColor(int value) {
switch(value){
case 1: return Color.RED;
case 2: return Color.GREEN;
//TODO the rest of colors
}
return Color.DARK_GRAY;
}
}
还要注意,由于您要为整数列设置渲染器,因此请确保您的模型在其
getColumnClass()
实现中实际上返回了一个有效的类。否则,将不使用渲染器。例如,DefaultTableModel.getColumnClass()
为所有列返回Object.class
。getColumnClass()
返回描述存储在指定列中的数据对象的类。 JTable
使用它为该列分配默认的渲染器和编辑器。在您的情况下,如果您在模型中存储整数,则getColumnClass()
应该返回Integer.class
。但是请注意,Integer.class
和int.class
是不同的。因此,setDefaultRenderer
应该对应于getColumnClass
返回的类。就您而言,在两个地方都是int.Class
或Integer.Class
。另外一点,请查看How to Use Key Bindings,因为关键侦听器是较低级别的界面