Java Forum / First Aid / July 2008
display a TableModel as a JTable
thufir - 03 Jul 2008 11:16 GMT Given three classes:
View JFrame for the GUI MyTableModel represents the data DBDemo has db connection
In View there's:
private javax.swing.JTable db; db.setModel(MyTableModel.getInstance());
Should DBDemo, which connects to the actual database, morph into an inner class for MyTableModel, perhaps?
From the view, how do I make the JTable synchronize with the MyTableModel instance? A listener of some sort?
code:
thufir@arrakis:~$ thufir@arrakis:~$ cat NetBeansProjects/ubuntu-jdbc/src/a00720398/model/ MyTableModel.java package a00720398.model;
import javax.swing.table.*;
public class MyTableModel extends AbstractTableModel {
private static final TableModel INSTANCE = new MyTableModel(); private MyTableModel() {} public static TableModel getInstance() { return INSTANCE; }
public int getColumnCount() { return 1; //dummy }
public String getColumnName(int i) { return "foo"; }
public int getRowCount() { return 3; }
public Object getValueAt(int row, int col) { return new Object(); //critical to fill this in }
} thufir@arrakis:~$ thufir@arrakis:~$ cat NetBeansProjects/ubuntu-jdbc/src/a00720398/model/ DBDemo.java package a00720398.model;
import java.sql.*; import java.util.Properties;
public class DBDemo {
private static final String DBCLASSNAME = "com.mysql.jdbc.Driver"; private static final String CONNECTION = "jdbc:mysql://localhost/ COFFEEBREAK";
public void db() throws ClassNotFoundException, SQLException {
Class.forName(DBCLASSNAME);
Properties p = new Properties(); p.put("user", "java"); p.put("password", "password");
Connection c = DriverManager.getConnection(CONNECTION, p);
Statement stmt = c.createStatement();
stmt.executeUpdate("CREATE TABLE COFFEES " + "(COF_NAME VARCHAR(32), SUP_ID INTEGER, PRICE FLOAT, " + "SALES INTEGER, TOTAL INTEGER)");
stmt.executeUpdate("INSERT INTO COFFEES " + "VALUES ('Colombian', 101, 7.99, 0, 0)"); stmt.executeUpdate("INSERT INTO COFFEES " + "VALUES ('French_Roast', 49, 8.99, 0, 0)"); stmt.executeUpdate("INSERT INTO COFFEES " + "VALUES ('Espresso', 150, 9.99, 0, 0)"); stmt.executeUpdate("INSERT INTO COFFEES " + "VALUES ('Colombian_Decaf', 101, 8.99, 0, 0)"); stmt.executeUpdate("INSERT INTO COFFEES " + "VALUES ('French_Roast_Decaf', 49, 9.99, 0, 0)");
String query = "SELECT COF_NAME, PRICE FROM COFFEES"; ResultSet rs = stmt.executeQuery(query); while (rs.next()) { String s = rs.getString("COF_NAME"); float n = rs.getFloat("PRICE"); System.out.println(s + " " + n); }
String updateString = "UPDATE COFFEES " + "SET SALES = 75 " + "WHERE COF_NAME LIKE 'Colombian'"; stmt.executeUpdate(updateString);
c.close(); } }
thufir@arrakis:~$ thufir@arrakis:~$
thanks,
Thufir
RedGrittyBrick - 03 Jul 2008 14:14 GMT > Given three classes: > [quoted text clipped - 4 lines] > From the view, how do I make the JTable synchronize with the MyTableModel > instance? A listener of some sort? For a model that implements AbstractTableModel, as your's does, the usual method is to pass the model to the table's constructor:
JTable table = new JTable(MyTableModel.getInstance())
 Signature RGB
Mark Space - 03 Jul 2008 16:16 GMT > From the view, how do I make the JTable synchronize with the MyTableModel > instance? A listener of some sort? First, I think I'd keep anything which has a DB connection away from Swing. This feels like mixing layers. I'd invent a bean that contained the actual data, then compose the Swing table model with that bean.
Also, the static fields in MyTableModel smell bad to me.
public class MyJFrame extends JFrame
private MyTableModel tableModel; private JTable viewTable;
public MyJFrame( MyBean b ) { tableModel = new MyTableModel( b ); // Make table model with data viewTable = new JTable( tableModel ); // ... etc. finish JFrame here... }
public static main( String ... args ) { // Set up database connection and query...
ResultSet rs = //...
MyBean bean = new MyBean( rs ); // build bean from result set new MyJFrame( bean ).setVisible( true ); // show the result }
}
class MyTableModel extends AbstractTableModel {
private MyBean data;
public MyTableModel( MyBean b ) { data = b.clone(); // defensive copy } // Other methods pretty much as you had them...
}
// MyBean is "whatever" ... just some data with getters and setters.
So after sketching out the program above, I found that my "synchronization" came from making a defensive copy. So I avoid any actual synchronization. This seems like the best way, as a general case. If you could produce something that's closer to your actual code or explain why you think you need synchronization, we might be able to help with some specifics.
Listeners in Swing run on the EDT, so there's no need to synchronize with any Swing internal data (like models like AbstractTableModel). The EDT is of course not synchronized with any events external to Swing, so you have to deal with those yourself. It's this latter case -- events external to Swing -- that I don't feel like I have enough information on.
thufir - 03 Jul 2008 21:48 GMT > So after sketching out the program above, I found that my > "synchronization" came from making a defensive copy. So I avoid any [quoted text clipped - 9 lines] > external to Swing -- that I don't feel like I have enough information > on. Oh, to clarify, I mean synchronize as in what's seen in the view matches the underlying data, I wasn't referring to the Synchronized interface. Sorry, poor word choice which looks to have confused things.
I just read a bit of Dietel, it looks like he uses
http://java.sun.com/javase/6/docs/api/javax/swing/table/ AbstractTableModel.html#fireTableChanged (javax.swing.event.TableModelEvent)
to get the JTable to match the underlying db.
-Thufir
Mark Space - 03 Jul 2008 23:22 GMT > I just read a bit of Dietel, it looks like he uses > > http://java.sun.com/javase/6/docs/api/javax/swing/table/ > AbstractTableModel.html#fireTableChanged > (javax.swing.event.TableModelEvent) Remember, this still might require synchronization, as in the keyword.
If you do your update of the model data in the EDT, then it's possible the the result set or whatever object you use is being updated by the database object at the same time. If you work eternally to the EDT, the the model itself (accessed by the AbstractTableModel object) might be updated by the GUI while trying to respond to some external user event.
You maybe way ahead of me here, I haven't used JTables explicitly, but I've done a little work some some of the other Swing objects, and they do require attention to the EDT. Usually, you end up passing a Runnable to java.awt.EventQueue.invokeLater to synchronize updating the model, but you might have a more efficient way of doing it.
thufir - 05 Jul 2008 11:23 GMT > If you do your update of the model data in the EDT, then it's possible > the the result set or whatever object you use is being updated by the > database object at the same time. If you work eternally to the EDT, the > the model itself (accessed by the AbstractTableModel object) might be > updated by the GUI while trying to respond to some external user event. Of course, but that's an immediate concern :)
-Thufir
Mark Space - 04 Jul 2008 00:20 GMT > I just read a bit of Dietel, it looks like he uses > > http://java.sun.com/javase/6/docs/api/javax/swing/table/ > AbstractTableModel.html#fireTableChanged > (javax.swing.event.TableModelEvent) Also, read the docs. This says:
"Forwards the given notification event to all TableModelListeners that registered themselves as listeners for this table model. "
So all it does is kick off the listeners, which you have to add yourself anyway.
Most Swing methods are not thread-safe either, so check carefully before calling this method when you are not executing on the EDT. I don't think fire* methods are on the safe list, although several types of listener methods are thread-safe, so a careful investigation might reveal some documentation saying this one is. Otherwise, you have to assume it's not.
<http://java.sun.com/docs/books/tutorial/uiswing/concurrency/initial.html>
There should be a part of the Java doc where it explains (briefly) the Swing threading model, and what methods are thread-safe. I don't see it right now however, so no link, sorry.
Nick - 17 Jul 2008 03:52 GMT [...]
> First, I think I'd keep anything which has a DB connection away from > Swing. This feels like mixing layers. I'd invent a bean that contained > the actual data, then compose the Swing table model with that bean. [...]
Aha. If the underlying data is a bean, then just compose the Table Model with that bean. Can you use bean binding so that changes to the underlying data percolate up to the Table Model and then to the JTable?
thanks,
Thufir
Lew - 04 Jul 2008 02:00 GMT > I wasn't referring to the Synchronized interface. That's good, because I don't think any of us have heard of the Synchronized interface. I'm going to guess that you meant something different, though, not actually an interface called "Synchronized".
> I mean synchronize as in what's seen in the view matches > the underlying data Yes, that would be synchronization as the other respondents meant it, the thing that gets coordinated via the 'synchronized' keyword and other mechanisms.
 Signature Lew
Thufir - 12 Jul 2008 10:28 GMT [...]
> Yes, that would be synchronization as the other respondents meant it, the > thing that gets coordinated via the 'synchronized' keyword and other mechanisms. [...]
Here's the usage I meant:
Beans Binding is a Java platform library defined by Java Specification Request 295. JSR 295 is an open source project that tries to simplify how developers synchronize two properties, usually in two different objects. The JSR has a reference implementation available as the Beans Binding project on java.net. Additionally, NetBeans IDE 6 includes the latest release of the Beans Binding library, making it easy for NetBeans users to try out the new library.
Synchronizing Properties with Beans Binding (JSR 295) by John O'Conner 03/20/2008
-Thufir
Nick - 17 Jul 2008 02:55 GMT [...]
> First, I think I'd keep anything which has a DB connection away from > Swing. This feels like mixing layers. I'd invent a bean that contained > the actual data, then compose the Swing table model with that bean. [...]
Aha. If the underlying data is a bean, then just compose the Table Model with that bean. Can you use bean binding so that changes to the underlying data percolate up to the Table Model and then to the JTable?
thanks,
Thufir
thufir - 17 Jul 2008 06:13 GMT > I'd invent a bean that contained > the actual data, then compose the Swing table model with that bean. Aha. If the underlying data is a bean (or accessed via a bean?), then just compose the Table Model with that bean? Can you use bean binding so that changes to the underlying data percolate up to the Table Model and then to the JTable?
thanks,
Thufir
Free MagazinesGet these publications absolutely FREE for up to 12 months. There are no hidden fees and no obligation. Simply choose a title, complete the application form and submit it. Read more ...
|
|
|