tags:

views:

565

answers:

3

Hi All, I am trying to create simple application where JTable gets updated and refreshed after data is changed.Structure is as follows. 1)Class Main which contains JFrame,JTable details. 2)SampleTableModel class which extends AbstractTableModel.I am overriding most of the methods.

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);
    }
}

As you can see, notifyTable will be called from another class(which is actually a thread-which calls this method frequently) Problem is I don't see data being changed in JTable.I see only the initialized data. In the Main class- I am setting like this-

RVJDataTable.setModel(new SampleTableModel());
+1  A: 

In general, Swing is not thread safe. Consider using EventQueue.invokeLater(), mentioned here.

Addendum: Given your updated example, try something like this:

@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();
        }
    }
}

Addendum: SwingWorker, discussed here is another alternative means of updating the GUI from another thread.

trashgod
Added example of `EventQueue.invokeLater()`.
trashgod
A: 

Based on the code provided it looks like it should work but the code is not complete so I can't say for sure. Maybe your "other" class has a reference to the wrong TableModel?

Also, there is nothing special about your data so why not just use the DefaultTableModel. You can then update the table using:

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

If you need more help post your SSCCE.

camickr
A: 

hi I am using DefaultTableModel instead of Abstract one to insert data.

This is he main 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

} Following class is used to define 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;
}

} and follwing class adds record every 5 seconds using Stock class.

   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);
    }
}

} I don't see JTable getting updated.

This should be an edit to your question; only you get notified of new answers.
trashgod