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

时间:2014-07-14 18:55:48

标签: java swing jtable swingworker

我对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);
    }
}
addRows方法调用

SwingWorker.process方法。 有趣的是,rowCount总是正确的,但JTable上没有显示行。

我尝试了一切,没有任何帮助。 我想创建短暂的可运行的演示,但我无法实现这个错误。

我发布了这个项目on github,并描述了那里的错误。

2 个答案:

答案 0 :(得分:1)

camickr是正确的,实际上有两个你的VirusTable实例(实际上也是MainFrame,但其中只有一个是可见的)正在创建。您已经提供了一种通过基本上将其转换为单例来访问MainFrame对象的方法,但没有约束条件,即只能创建一个实例。恕我直言,如果不在MainFrame类中创建静态getInstance方法,你可以做得更好。

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

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);
        }
    });
}

感谢camickr,不是我。

答案 1 :(得分:0)

也许您正在从事件调度线程以外的线程更改Swing模型(很难从代码中判断出来)?所有Swing交互必须从EDT完成,因此要么将表更新包装在SwingUtilities.invokeLater()中(如果您希望在找到每个条目时更新它),或者在done()方法中将项添加到表模型中SwingWorker强制在EDT上执行。