我在为 JTable 单元格着色时遇到问题。我正在制作俄罗斯方 block 游戏。游戏的所有功能都有效;按下按钮、移动棋子的键盘交互、删除完整的行等。现在发生的输出只是打印出的表格整数值(见屏幕截图)。这些整数值指的是一种颜色。我有代码根据下面 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作为关键听众是一个较低级别的接口(interface)
关于java - 为 JTable 单元格着色,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15605741/