我在给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的扩展(请注意,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,因为关键侦听器是较低级别的界面

09-30 14:11