2010-05-29 156 views
1

我想創建一個簡單的應用程序,其中JTable在數據更改後得到更新和刷新。結構如下。 1)包含JFrame,JTable細節的類Main。 2)擴展了AbstractTableModel.I的SampleTableModel類覆蓋了大多數方法。JTable插入行並刷新

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.I改變只能看到初始化數據。 在主講座我設置像這個 -

RVJDataTable.setModel(new SampleTableModel()); 

我使用的DefaultTableModel,而不是抽象的插入數據。

這是他主要的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; 
} 

} 和follwing類將使用股票類每5秒記錄。

public class Updater { 

public static void main(String[] args){ 
    Stock stock =new Stock(); 
    stock.start(); 
} 

} 類股票繼承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中得到更新。

回答

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的另一替代手段。

+0

添加'EventQueue.invokeLater()'的例子。 – trashgod 2010-06-01 13:18:27

1

基於提供的代碼,它看起來應該可以工作,但代碼不完整,所以我不能肯定地說。也許你的「其他」類引用了錯誤的TableModel?

此外,沒有什麼特別的關於您的數據,所以爲什麼不使用DefaultTableModel。然後,您可以使用更新表:

table.setValueAt(123, 0, 0); 
table.setValueAt(456, 0, 1); 

如果您需要交的SSCCE更多的幫助。