java - Swing JTable 的重绘表问题

标签 java swing jtable

我正在使用 swing JTable,并且在重新绘制表格时遇到问题。我用下面的代码绘制了一个JTable

Object[] column = new Object[]{"Entity", "Attribute"};
Object[][] rowData = new Object[][]{{"E1", "A1"},{"E2", "A2"}};
TableCellRenderer cellRenderer = new TableCellRenderer();

JTable table = new JTable(new DefaultTableModel(rowData, column));

table.setCellSelectionEnabled(true);

table.getColumnModel().getColumn(0).setCellRenderer(cellRenderer);

下面是我的表格渲染器代码..

public class TableCellRenderer implements javax.swing.table.TableCellRenderer {

//private JPanel panel;
JTextField field;
private JTable table;   

@Override
public Component getTableCellRendererComponent(final JTable table, final Object value,
        boolean isSelected, boolean hasFocus, final int row, final int column) {

    this.table = table;
    //JTextField field = null;
    System.out.println("Rendere : Row : " + row + "Column : " + column);
    final JPanel panel = new JPanel();
    panel.setLayout(new BorderLayout());

    JButton button = new JButton("?");
    button.setPreferredSize(new Dimension(20, panel.getHeight()));
    button.addActionListener(new ActionListener() {

        @Override
        public void actionPerformed(ActionEvent arg0) {
            new SelectionDialog(panel, table, value, row, column);

        }
    });
    if(table.getValueAt(row, column) != null){
        field = new JTextField(table.getValueAt(row, column).toString());
    }else{
        field = new JTextField(table.getValueAt(row, column).toString());
    }
    field.setPreferredSize(new Dimension(30, panel.getHeight()));
    panel.add(field, BorderLayout.WEST);
    panel.add(button, BorderLayout.EAST);

    return panel;

}

这就是我更新表中单元格内容的方式..

SelectionDialog.this.table.getModel().setValueAt("E7", 0, 0);

我正在通过 SelectionDialog 更新表模型数据,例如将第 0 行、第 0 列的数据更改为 E7 等。更改表模型中的数据后,我尝试了以下选项,但没有一个已刷新 View 中的表数据,但是 JTable 模型中的数据已正确更新。如果我动态添加一个新行,然后调用以下方法,那么一切都会正常工作,但是如果我修改现有行模型中的数据,那么下面提到的解决方案都不起作用

//((DefaultTableModel)SelectionDialog.this.table.getModel()).addRow(new Object[]{"E3", "A3"});
            //((DefaultTableModel)SelectionDialog.this.table.getModel()).fireTableCellUpdated(SelectionDialog.this.row, SelectionDialog.this.column);
            //((DefaultTableModel)SelectionDialog.this.table.getModel()).fireTableChanged(new TableModelEvent(SelectionDialog.this.table.getModel()));
            //((DefaultTableModel)SelectionDialog.this.table.getModel()).fireTableStructureChanged();
            //SelectionDialog.this.table.repaint();
        //  SelectionDialog.this.table.revalidate();

请提供有关该问题的任何见解,因为我正在 Swing ,并且可能错过了一些非常重要的事情。

编辑1:只是添加了一个注释,我想提前放置它,但不知道我是如何错过的。表格通常不会更新,但如果我将注意力从进行更改的单元格中移开,或者更改表格的大小,那么它会立即将该特定单元格的内容更改为新选择的值。

问题已解决:

我将我的发现提供给面临类似问题的人。

我在表格的每个单元格内渲染了一个按钮和一个文本框。单击按钮时(未提供编辑器代码,因为它看起来与我无关,放置在此处)会出现一个对话框,其中输入用户的值并更新特定的列和行。 我在帖子末尾提到的行(在编辑 1 之前)无法正常工作,但是渲染器无法执行,除非我手动将焦点从选定的单元格(单击了其按钮)中移开,或者手动更改 jtable 的大小,这使得感觉按钮位于编辑器内,并且单击按钮显示单元格已被编辑,除非编辑完成(需要焦点移出或输入键等),否则偏离路线的渲染器将不会执行。 我将以下代码应用为

table.editCellAt(-1, -1);

它将焦点从已编辑的单元格(使用按钮编辑)中移出,因此渲染器会按预期执行和工作。

最佳答案

当您使用DefaultTableModel并且想要更新某个值时,需要使用DefaultTableModel#setValueAt方法。

调用此方法(当然是在事件调度线程上)将更新您的模型并触发必要的事件。这些事件将导致您的 JTable 自行更新。

关于渲染器的一些附加说明:

  • 在渲染器的每次调用中创建新组件并不是正确的方法。对于大表来说,这变得非常慢。在渲染器的构造函数中创建所有组件一次,然后更新它们的状态
  • 向渲染器中的表格添加 JButton 没有任何效果,除非您也有编辑器。该按钮将不可单击,并且您附加到它的操作监听器将永远不会被调用。请参阅renderers and editors section in the JTable tutorial了解更多信息。
  • 无需在渲染器中调用 getValueAt。该值作为参数之一传入

关于java - Swing JTable 的重绘表问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30963616/

相关文章:

java - 如何在 J2ME 中获取和设置 JSONObject , JSONArray

java - Maven 拉取旧版本的传递依赖

java - 从另一个类刷新 JTable

java - 我应该如何构建一个必须使用 Spring 和 JPA 的模块化企业应用程序?

java - 生产者消费者模式: on demand thread

java - 关闭第二个屏幕后,图形环境不会更新屏幕设备

java - 重新排序滚动 Pane 中的面板

java - 自定义滚轮监听器阻止 ScrollPane 滚轮监听器

java - 结果集显示 jTable 的前 12 行为空 - Java

java - JTable AutoCreateRowSorter 将数字排序为字符串