JTable插入行并刷新

时间:2010-05-29 18:13:58

标签: java swing jtable

我正在尝试创建简单的应用程序,其中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得到更新。

2 个答案:

答案 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