1

我无法为我的 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);
    }
}

俄罗斯方块截图

4

1 回答 1

3

您不应该在渲染器的getTableCellRendererComponent(). JTable为所有单元重用一个渲染器。在您的情况下,您多次为每个单元分配新组件。有关详细信息,请参阅如何使用表教程中的概念:编辑器和渲染器。考虑这个扩展(注意它是 的扩展):DefaultTableCellRendererDefaultTableCellRendererJLabel

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.Class在两个地方或Integer.Class.

另一点,看看如何使用键绑定作为键侦听器是一个较低级别的接口

于 2013-03-25T00:38:55.163 回答