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();
}
}
如果要扩展DefaultTableModel
,那么当数据发生更改时,需要使用setValueAt
或setDataVector
方法在DefaultTableModel
的内部表示中更新数据。如果您有大量的更改(听起来像这样),请使用setDataVector
方法一次更改所有单元格和表结构。您的示例代码看起来缺少一些更新,因为它没有将新值推送到DefaultTableModel
的数据向量中。
但是由于您有很多更新,您可能最好避免使用< code>DefaultTableModel,而只是扩展< code>AbstractTableModel,使用您自己的自定义数据存储,并在数据发生变化时调用适当的< code>fireXxx()方法。就数据转换和引发的事件数量而言,这可能会更有效。
然后使用< code>SwingWorker或其他线程支持,确保所有事件和值更改工作都在AWT事件线程上完成。