Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations Mike Lewis on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

Swing refresh problem

Status
Not open for further replies.
May 13, 2002
75
0
0
GB
Hi,

struggling with some basic swing code, excuse the bad practises here, but i've created a simple example of a JTable and a JButton in a JFrame, when i click the button the table should change but it doesn't. The code is posted below, i've tried all sorts of cominations of using repaint, revalidate, updateUI methods but cannot get the thing to behave how i want. Any ideas ??

Code:
package com.myempire;

import javax.swing.*;
import javax.swing.event.*;
import java.awt.event.*;

public class SwingTest extends JFrame
{

JPanel jp;
JScrollPane js;
JTable jt;

Object[][] data = {
    {"Mary", "Campione", 
     "Snowboarding", new Integer(5), new Boolean(false)},
    {"Alison", "Huml", 
     "Rowing", new Integer(3), new Boolean(true)},
    {"Kathy", "Walrath",
     "Chasing toddlers", new Integer(2), new Boolean(false)},
    {"Mark", "Andrews",
     "Speed reading", new Integer(20), new Boolean(true)},
    {"Angela", "Lih",
     "Teaching high school", new Integer(4), new Boolean(false)}
};


Object[][] data2 = {
    {"Mary", "Campione", 
     "Snowboarding", new Integer(5), new Boolean(false)},
    {"Alison", "Huml", 
     "Rowing", new Integer(3), new Boolean(true)}
};
String[] columnNames = {"First Name", 
                        "Last Name",
                        "Sport",
                        "# of Years",
                        "Vegetarian"};


  public SwingTest()
  {
    jp = new JPanel();
    jt = new JTable(data,columnNames);
    js = new JScrollPane(jt);
    
    JButton jb = new JButton("Click to change table");
    jb.addActionListener(new buttonHandler());
    
    jp.add(jb);
    jp.add(js);

    this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    this.getContentPane().add(jp);  

  }


private class buttonHandler implements ActionListener{
  public void actionPerformed(ActionEvent e){
    jt = new JTable(data2,columnNames);
  }

}

  public static void main(String[] args)
  {
    SwingTest swingTest = new SwingTest();
    swingTest.show();
  }
}

Thanks


Alistair [monkey]
 
One way you can handle this is to create a TableModel object to hold your data, rather than the array of objects you have now.

Then you can use the fireTableDataChanged() method to cause the table to update itself.
 
OK, the problem i have is that when the button is pressed i am calling a method that returns a class that extends JTable, so i don't have the TableModel itself.

I know that it's not ideal for a method in another class to return a class that extends JTable but i have to live with it [neutral].

Thanks

Alistair [monkey]
 
There are a number of reasons what you're trying to do wont work.

You added a JTable to the JPanel using jp.add(js), however when you set jt = new JTable(data2,columnNames) you are simply creating another JTable, and setting the jt reference variable accordingly. The panel is still using the original table you gave it.

You could therefore remove the table from the panel and add the new table. (not recommended) OR, change the Table's model, then inform it of the change and the view will update. (preferred method).

A JTable uses the Model-View-Controler MVC pattern. The View is what you see on the screen, the controller is the object that created the data, and/or changes it. The model is where the data is stored. You constructed the JTable by giving it an array of data, this is then stored inside the JTable as a TableModel. You could have created a TableModel before the constructor, and given it as an argument to the JTable constructor.

The JTable has a method getModel() which returns an object that implements the TableModel interface (If you constructed it with a TableModel, this object would be returned.). In your example, the JTable has created (internally) a DefaultTableModel to store your data. This is the object getModel() returns.

Unfortunately TableModel does not have a method fireTableDataChanged(), but DefaultTableModel does (in fact it inherited it from AbstractTableModel) . You will therefore have to cast the return TableModel to a AbstractTableModel. Then you can call fireTableDataChanged().
Code:
try {
  AbstractTableModel model = (AbstractTableModel)jt.getModel();
  // change the data
  model.fireTableDataChanged();
}
  catch (CastClassException e) {
  // handle error if the model returned by the JTable is not a AbstractTableModel.
}

Alternatively, you could create a second TableModel when the button is pressed, and call the JTable's setModel(TableModel model) to change the JTable's internal model. The side effect of doing this is that the setModel() also updates the view.

Code:
DefaultTableModel model = new DefaultTableModel(data2,columnNames);
jt.setModel(model);

Clearly the 2nd technique is better! and is a classic example of a Model-View-Controller pattern.

hope this helps.

PS this ( is a useful web site with lots of examples of JTable code. And generally is a good site to lookup everyday examples of how to use the J2SE classes.
 
I had almost the same problem with changing the content of a JPanel: Calling the following two functions has solved the problem in my case:

validate();
repaint();
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top