2010-05-29 2 views
1

Я пытаюсь создать простое приложение, в котором JTable обновляется и обновляется после изменения данных. Структура выглядит следующим образом. 1) Класс Main, который содержит JFrame, JTable детали. 2) Класс SampleTableModel, который расширяет AbstractTableModel. Я переопределяю большинство методов.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 см только инициализированные данные. В основном классе я устанавливаю как this-

RVJDataTable.setModel(new SampleTableModel()); 

Я использую DefaultTableModel вместо абстрактно для вставки данных.

Это он главный JTable class-

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 секунд, используя Stock класс.

public class Updater { 

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

} класс Stock расширяет тему {

//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

1

На основании предоставленного кода, похоже, что он должен работать, но код не является полным, поэтому я не могу сказать точно. Может быть, ваш «другой» класс имеет ссылку на неправильную таблицу?

Кроме того, нет ничего особенного в ваших данных, поэтому почему бы просто не использовать DefaultTableModel. После этого вы можете обновить таблицу, используя:

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

Если вам нужна дополнительная помощь после вашего SSCCE.

Смежные вопросы