提问者:小点点

如何使用不断变化的表模型刷新 JTable?


2015.5.5 22:11更新。我发现,当我在MyTable的构造中创建一个sorter并调用setRowSorter()方法后,它会保持原来的行号(其中的数据仍然正确刷新,但不容易被发现),即使里面的dataModel已经被改变了很多次,这可以证明为printf(getModel()。getRowCount())。而且MyTable.getAutoCreateRowSorter()总是返回true。如果我调用setRowSorter(),我必须显式调用setAutoCreateRowSorter(true)来解决这个问题。我很高兴,但这仍然很奇怪。

[2015.5.5 6:19 已更新]我找到了一种访问方法:使用 insertRow() 和 removeRow() 的组合创建一个“setRow”,每次更新时,我都会设置表中的所有行。它会立即反映在 UI 中。但是会有一系列以“AWT-EventQueue-0”开头的错误java.lang.IndexOutOfBoundsException:无效索引“,我想这是关于一些摆动线程问题,因为我可以在错误中看到”RepaintManager“或”paint”。特别是当我在运行时移动滚动条时,会发生这种情况。(但如果我不移动它,它仍然会发生)

我在JFrame中的JScrollPane中有一个Jtable。我用数据初始化MyTableModel并使用它来创建JTable。像这样

MyTableModel extends DefaultTableModel{
    Data data;
    //object

    MyTableModel (Data a){
    data = a;
    // do something to initial the table model,like build object[][] and add rows.   
    }
}
class main{
MyTableModel tm = new MyTableModel(data);
Jtable table = new JTable(tm);
JScrollpane jsp = new JScrollpane(table);
JFrame window = new JFrame();
window.getxxxpane().add(jsp);



}

所以,由于我的数据总是在变化/更新,变化的行是复数,不可能计算。

while(true){
    data.change();

    refreshing the table to display the data immediately;

}

我的想法是简单地构建一个新的MyTableModel对象,并将其设置为表的模型,如:

 table.setModel(new MyTableModel(data));   //data had been changed.

这不管用。我试着这样做:

  tm = MyTableModel(data);
  tm.fireTableDataChanged();

这也不起作用。以及组合:

  MyTableModol nm = new MyTableModel(data); //data had been changed
  table.setModel(nm);
  nm.fireTableDataChanged();

有人可以给我一些线索来更改不可更改的 Jtable 中的 TableModel 对象并每次更新。我不想更改表模型对象,因为计算量很大,相反,我想始终使用构造方法的参数(更改的数据)创建一个新对象。

最差的方法是移除JScrollpane,重新构建一个table/tablemodel/jscrollpane重新添加,其中我要调用window.setVisible(true)。window.repait()也不起作用,除非我移动它。我创建了一个浪费空间但可运行的演示程序,其中大部分都是无意义的。

import java.awt.BorderLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.Formatter;

import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JScrollPane;
import javax.swing.JTabbedPane;
import javax.swing.JTable;
import javax.swing.table.DefaultTableModel;

class TM extends DefaultTableModel {
    int[] inside;
    static String[] columnNames = { "Hellium", "Radon",

    };

    TM(int[] data) {
        super(columnNames, 0);
        this.inside = data;
        update();
    }

    void update() {
        Object[][] data = new Object[2][columnNames.length];

        for (int i = 0; i < 2; ++i) {

            data[i][0] = inside[0];

            data[i][1] = inside[1];
           // setValueAt(aValue, row, column);
            addRow(data[i]);

        }
        fireTableDataChanged();
    }

}

class idkName {
    TM tm;
    JButton jb, jb2;
    int data[] = { 1, 2 };
    int data2[] = { 9, 10 };
    JTable table;
    JScrollPane jsp;
    JFrame twindow;

    idkName() {
        JFrame window = new JFrame();
        window.setSize(400, 400);
        window.setLayout(new BorderLayout());
        jb = new JButton("show");
        jb2 = new JButton("change model");
        window.add(jb, BorderLayout.EAST);
        window.add(jb2, BorderLayout.WEST);
        twindow = new JFrame();

        jb.addActionListener(new ActionListener() {

            @Override
            public void actionPerformed(ActionEvent arg0) {
                tm = new TM(data);
                table = new JTable(tm);
                jsp = new JScrollPane(table);
                twindow.getContentPane().add(jsp);
                twindow.setSize(500, 500);
                twindow.setVisible(true);

            }
        });
        window.setVisible(true);

        jb2.addActionListener(new ActionListener() {

            @Override
            public void actionPerformed(ActionEvent e) {
                // TODO Auto-generated method stub
                // tm = new TM(data2);

                tm = new TM(data2);

                System.out.println(""+tm.getValueAt(0,0));
                tm.fireTableDataChanged(); 
                twindow.setVisible(true); 

            }
        });

    }
}
public class main2 {
    TM tm;
    public static void main(String[] args) {
        idkName i = new idkName();
    }

}

共1个答案

匿名用户

如果要扩展DefaultTableModel,那么当数据发生更改时,需要使用setValueAtsetDataVector方法在DefaultTableModel的内部表示中更新数据。如果您有大量的更改(听起来像这样),请使用setDataVector方法一次更改所有单元格和表结构。您的示例代码看起来缺少一些更新,因为它没有将新值推送到DefaultTableModel的数据向量中。

但是由于您有很多更新,您可能最好避免使用< code>DefaultTableModel,而只是扩展< code>AbstractTableModel,使用您自己的自定义数据存储,并在数据发生变化时调用适当的< code>fireXxx()方法。就数据转换和引发的事件数量而言,这可能会更有效。

然后使用< code>SwingWorker或其他线程支持,确保所有事件和值更改工作都在AWT事件线程上完成。