tags:

views:

69

answers:

4

I am trying to implement a ListSelectionListener for some of my JTables. Simply (at the moment) the ListSelectionListener is supposed to simply return the text of the cell that was selected.

My program design has several JTables and I would like to have one ListSelectionListener work for them all. In the valueChanged event of the ListSelectionListener I thought it was possible to do something like:

private class SelectionHandler implements ListSelectionListener {
    public void valueChanged(ListSelectionEvent e)
    {
        JTable table = (JTable)e.getSource();                                                         

        String data = (String) table.getValueAt(table.getSelectedRow(), 0);

        // Print data
    }
}

Behind the scenes I have used the following code to get the SelectionHandler working with the table in question:

fbTable.setCellSelectionEnabled(true);
ListSelectionModel cellSM = fbTable.getSelectionModel();
cellSM.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
cellSelectionModel.addListSelectionListener(selectionHandler);

When I run the program I get a ClassCastException error:

Exception in thread "AWT-EventQueue-0" java.lang.ClassCastException: javax.swing.DefaultListSelectionModel cannot be cast to javax.swing.JTable
        at cardboardfantasy.CardboardFantasyView$SelectionHandler.valueChanged(CardboardFantasyView.java:360)

// This is the line in question: JTable table = (JTable)e.getSource();

Is there a way to do something like this? One solution I thought of was to compare the source of the event (e.getSource()) to all my JTables to see if they were equivalent (big if block) and then just calling .getValueAt inside that block but that would making the code in the future difficult if tables were to be added or removed.

+1  A: 

Either debug your code in your IDE, set a breakpoint and see what the type of e.getTarget() is:

Object source = e.getSource();
JTable table = (JTable)source; // breakpoint on this line and inspect the variable 'source'
String data = (String) table.getValueAt(table.getSelectedRow(), 0);

Or if debugging is not possible for whatever reason do this:

Object source = e.getSource();
System.out.println(source.getClass());

But: debugging using System.out.println is evil. your debugger is your friend.

seanizer
I went ahead and used this method: Object source = e.getSource();System.out.println(source.getClass()); and found that the source wasn't what I expected. Its of class javax.swing.DefaultListSelectionModel. This means I obviously don't know how make this work with JTables. Is there a way to find out which JTable the DefaultListSelectionModel is associated with?
Chris
I'm not a swing pro, I just know my java. Haven't done swing since 2003 :-)Anybody else?
seanizer
I don't agree that print statements are evil, but +1 for the debugging tips.
Amir Afghani
print statements as such are not evil, but System.out.println is. Any logging framework provides a log.debug() method which is much better suited for the task
seanizer
+1  A: 

Hi,

As the error implies, the source object in question is a DefaultListSelectionModel not a JTable. This makes sense since the source of the event (that is, the object which fired the event) was the selection model object, not the table. Also, models in themselves make no assumptions about what type of object is using them as a model so there is no way to get a reference to the table via the selection model.

Avrom
A: 

Pass the JTable instance to your selection handler. As long as the handler listens on one table, you'll be able to use that instance instead of relying on the information from the event.

Kirill
A: 

I think there are two main solutions:

  • Use a JList and register the listener not with model but directly with the list. Then, if the list is contained by a table you could just ask for the list's (Component) parent to find the responsible table
  • Override DefaultListSelectionModel to (for example) take an additional argument in the constructor, which would be a JTable instance (every table will need a new instance of that model). You would save that instance in an instance variable and could then operate directly on the table when an event occurrs

I do not think that either of these solutions is ideal. I have the feeling that you could make your life easier by using some pattern or idiom to get around having to know which table the source was. But to give you any clues there we'd have to see a lot more of your code.

theseion