java - 为 JTable 单元格着色

标签 java swing user-interface jtable rendering

我在为 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);
    }
}

Tetris Screenshot

最佳答案

您不应在渲染器的 getTableCellRendererComponent() 中分配新组件。 JTable 为所有单元格重用一个渲染器。在您的情况下,您多次为每个单元格分配新组件。详情见Concepts: Editors and Renderers如何使用表格教程中。考虑 DefaultTableCellRenderer 的扩展(注意 DefaultTableCellRendererJLabel 的扩展):

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.classint.class 是不同的。所以 setDefaultRenderer 应该对应于 getColumnClass 返回的类。在您的情况下,两个地方的 int.ClassInteger.Class

还有一点,看How to Use Key Bindings作为关键听众是一个较低级别的接口(interface)

关于java - 为 JTable 单元格着色,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15605741/

相关文章:

java - 在 GUI 中逐项显示数组列表

java - 如何在extjs中将图表表格数据导出为PDF?

java - RandomAccessFile 对象的奇怪行为

java - 无法在 SettingsActivity 中解析 'AppCompatPreferenceActivity'

Java在线程中的循环中向JButton添加点击监听器

Java - JButton 监听器未触发

python - TKinter GUI,如何使帧的大小正确?

java - 在主类中处理按钮事件

java - Java程序帮助(Swing+数据库)

c# - 如何让我的程序成为后台进程