代码之家  ›  专栏  ›  技术社区  ›  Volodymyr Levytskyi

向DefaultTableModel添加新行时,JTable为什么不更新其视图?

  •  0
  • Volodymyr Levytskyi  · 技术社区  · 10 年前

    我对JTable有奇怪的问题。方法 addRows 不强制 jTable 更新其视图:

    public class VirusTable extends JTable {
    
        private String[] columnNames = { "", "Virus", "Path", "Size", "Created", "Last Mofified" };
    
        DefaultTableModel tableModel;
    
        public VirusTable() {
            super();
    
            tableModel = (DefaultTableModel) super.getModel();
            tableModel.setColumnIdentifiers(columnNames);
    
            // super.setFillsViewportHeight(true);
            // super.setIntercellSpacing(new Dimension(5, 5));
            // super.setRowSelectionAllowed(false);
            // super.setColumnSelectionAllowed(false);
        }
    
        public void addRows(Collection<UserFile> viruses) {
            System.out.println("AddRows=" + viruses);
    
            for (UserFile virus : viruses) {
                tableModel.addRow(virus.toRowData());
            }
    //      tableModel.fireTableDataChanged();
            // tableModel.fireTableStructureChanged();
            int rowCount = super.getRowCount();
    //      super.revalidate();
    //      super.repaint();
            System.out.println("rowCount=" + rowCount);
        }
    }
    

    添加行 方法是从调用的 SwingWorker.process 方法 有趣的是 rowCount 始终正确,但不显示行 JTable .

    我尝试了一切,但都无济于事。 我想创建一个简短的可运行演示,但我无法实现这个bug。

    我发布了此项目 on github 并描述了那里的问题。

    2 回复  |  直到 10 年前
        1
  •  1
  •   sgbj    10 年前

    camickr是正确的,实际上有两个VirusTable实例(事实上也有MainFrame,但只有一个可见)正在创建。您提供了一种访问MainFrame对象的方法,基本上是将其转换为单例,但没有只能创建一个实例的约束。IMHO,如果不创建静态 getInstance 方法。

    总之,在你的主要方法中,你这样做:

    public static void main(String[] args) throws IOException {
        SwingUtilities.invokeLater(new Runnable() {
    
            @Override
            public void run() {
                new MainFrame().setVisible(true);
            }
        });
    }
    

    但由于您编写应用程序的方式,您应该这样做(我不建议使用这种方法):

    public static void main(String[] args) throws IOException {
        SwingUtilities.invokeLater(new Runnable() {
    
            @Override
            public void run() {
                MainFrame.getInstance().setVisible(true);
            }
        });
    }
    

    谢谢卡米克,不是我。

        2
  •  0
  •   Kevin Day    10 年前

    也许您正在从事件分派线程以外的线程对Swing模型进行更改(从代码中很难看出)?所有Swing交互都必须在EDT中完成,所以要么在SwingUtility.invokeLater()中包装表更新(如果希望在找到每个条目时更新),要么在Swing Worker的done()方法中将项添加到表模型中,该方法强制在EDT上执行。