我正在尝试创建简单的应用程序,其中JTable在数据更改后得到更新和刷新。结构如下。 1)Class Main包含JFrame,JTable细节。 2)扩展AbstractTableModel的SampleTableModel类。我覆盖了大多数方法。
import javax.swing.table.*;
import java.util.*;
public class SampleTableModel extends AbstractTableModel {
public SampleTableModel() {
// this.addTableModelListener(
}
String[] columnNames = {"A", "B", "C", "D", "E"};
int[][] data = {{1, 2, 3, 4, 5}, {5, 6, 7, 8, 9}, {12, 13, 14, 15, 16}};
Vector dataVector = new Vector();
public Object getValueAt(int rowIndex, int columnIndex) {
return data[rowIndex][columnIndex];
}
public int getColumnCount() {
return 5;
}
public int getRowCount() {
return 3;
}
public String getColumnName(int columnIndex) {
return columnNames[columnIndex];
}
public void setValueAt(Object value, int row, int column) {
data[row][column] = 99;
}
public void notifyTable(AEMessage message) {
/*
* This method will be called from another class to update JTable.
* */
data[0][1] = 999;
data[0][2] = 8838;
data[1][1] = 8883;
fireTableRowsUpdated(0, 3);
}
}
如您所见,notifyTable将从另一个类调用(实际上是一个经常调用此方法的线程) 问题是我没有看到JTable中的数据被更改。我只看到初始化的数据。 在Main课程中 - 我设置如下 -
RVJDataTable.setModel(new SampleTableModel());
我使用DefaultTableModel而不是Abstract one来插入数据。
这是他主要的JTable类 -
import javax.swing.event.TableModelListener;
import javax.swing.event.TableModelEvent;
public class MainWindow extends javax.swing.JFrame implements TableModelListener {
public MainWindow() {
initComponents();
}
private void initComponents() {
jScrollPane1 = new javax.swing.JScrollPane();
// RVTableModel model = new RVTableModel();
TableModelWrapper wrap = new TableModelWrapper();
RVDataTable = new javax.swing.JTable();
setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE);
RVDataTable.setModel(wrap.getModel());
RVDataTable.getModel().addTableModelListener(this);
// RVDataTable.
jScrollPane1.setViewportView(RVDataTable);
javax.swing.GroupLayout layout = new javax.swing.GroupLayout(getContentPane());
getContentPane().setLayout(layout);
layout.setHorizontalGroup(
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(layout.createSequentialGroup()
.addGap(57, 57, 57)
.addComponent(jScrollPane1, javax.swing.GroupLayout.PREFERRED_SIZE, 552, javax.swing.GroupLayout.PREFERRED_SIZE)
.addContainerGap(105, Short.MAX_VALUE))
);
layout.setVerticalGroup(
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup()
.addContainerGap(25, Short.MAX_VALUE)
.addComponent(jScrollPane1, javax.swing.GroupLayout.PREFERRED_SIZE, 193, javax.swing.GroupLayout.PREFERRED_SIZE)
.addGap(82, 82, 82))
);
pack();
}// </editor-fold>
/**
* @param args the command line arguments
*/
public static void main(String args[]) {
java.awt.EventQueue.invokeLater(new Runnable() {
public void run() {
new MainWindow().setVisible(true);
}
});
}
public void tableChanged(TableModelEvent evt){
System.out.println(evt.getFirstRow());
}
// Variables declaration - do not modify
private javax.swing.JTable RVDataTable;
private javax.swing.JScrollPane jScrollPane1;
// End of variables declaration
} 以下类用于定义DefaultTableModel:
import javax.swing.table.*;
import javax.swing.event.*;
import java.util.*;
public class TableModelWrapper {
public DefaultTableModel getModel(){
Vector dataVec = new Vector();
String[] arr = {"ABS","ASAAS","ASAsA","AsaSA"};
Vector rowVec = new Vector();
for(int i=0;i<4;i++)
rowVec.add(i,arr[i] );
for(int i=0;i<5;i++)
dataVec.add(i, rowVec);
Vector columnNames = new Vector();
columnNames.add("FIRST");
columnNames.add("SECOND");
columnNames.add("THIIRD");
columnNames.add("FOURTH");
//columnNames.add("FIFTH");
DefaultTableModel model = new DefaultTableModel(dataVec,columnNames);
return model;
}
public Object[] getRecord(){
String[] arr = {"hhaHHA","HHHDS","NHHHSS","PQPPPQ"};
return arr;
}
} 并且使用Stock类,follewing类每5秒添加一次记录。
public class Updater {
public static void main(String[] args){
Stock stock =new Stock();
stock.start();
}
} class Stock extends Thread {
//RVTableModel model = null;
TableModelWrapper wrap = null;
public Stock(){
wrap = new TableModelWrapper();
}
public void run(){
try{
while(true){
wrap.getModel().addRow(wrap.getRecord());
wrap.getModel().fireTableRowsInserted(wrap.getModel().getRowCount() +1,wrap.getModel().getRowCount()+1);
sleep(5000);
}
}
catch(InterruptedException e){
System.out.println(e);
}
}
} 我没有看到JTable得到更新。
答案 0 :(得分:1)
通常,Swing不是线程安全的。考虑使用EventQueue.invokeLater()
,提及here。
附录:鉴于您的更新示例,请尝试以下方式:
@Override
public void run() {
while (true) {
EventQueue.invokeLater(new Runnable() {
@Override
public void run() {
wrap.getModel().addRow(wrap.getRecord());
}
});
try {
Thread.sleep(5000);
} catch (InterruptedException ex) {
ex.printStackTrace();
}
}
}
附录:SwingWorker
,讨论here是另一种从另一个线程更新GUI的替代方法。
答案 1 :(得分:1)
基于提供的代码,它看起来应该可以工作,但代码不完整所以我不能肯定地说。也许你的“其他”类引用了错误的TableModel?
此外,您的数据没有什么特别之处,所以为什么不使用DefaultTableModel。然后,您可以使用以下命令更新表:
table.setValueAt( 123, 0, 0 );
table.setValueAt( 456, 0, 1 );
如果您需要更多帮助,请发布SSCCE。