• Post Reply Bookmark Topic Watch Topic
  • New Topic
programming forums Java Mobile Certification Databases Caching Books Engineering Micro Controllers OS Languages Paradigms IDEs Build Tools Frameworks Application Servers Open Source This Site Careers Other Pie Elite all forums
this forum made possible by our volunteer staff, including ...
Marshals:
  • Campbell Ritchie
  • Jeanne Boyarsky
  • Ron McLeod
  • Paul Clapham
  • Liutauras Vilda
Sheriffs:
  • paul wheaton
  • Rob Spoor
  • Devaka Cooray
Saloon Keepers:
  • Stephan van Hulst
  • Tim Holloway
  • Carey Brown
  • Frits Walraven
  • Tim Moores
Bartenders:
  • Mikalai Zaikin

Extending AbstractTableModel and DefaultTableColumnModel

 
Ranch Hand
Posts: 479
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
I have a JTable in which I display different kinds of data; I have some integers, some strings, and some stuff for which I've written renderers.

I want my user to be able to choose things off a menu to select which columns are displayed, so the code needs to be able to insert/remove rows, etc.

The TableModel interface defines getColumnClass(int); it " Returns the most specific superclass for all the cell values in the column." AbstractTableModel.getColumnClass(int) "Returns Object.class regardless of columnIndex." DefaultTableModel does not implement the method.

My first thought was that TableColumn would have somewhere to store this column class, but it does not. I could extend TableColumn so that it had a "most specific superclass" stored for it; however, DefaultTableColumnModel stores its list of columns as a Vector<TableColumn>, so I can't store subclasses of TableColumn there (if you aren't familiar with generics, take my word for it or look it up). So if I store the column's class in an extension of TableColumn, that keeps me from using DefaultTableColumnModel or a subclass of it, or at least from storing my subclass of TableColumn in it.

The only two solutions I've thought of so far are (1) store the classes in a list in my own TableModel, separate from the 'real' list of TableColumns; this seems like a kludge, but a lot less trouble than (2) implementing TableColumnModel from scratch, so that it has a pass-through method for getting the column classes from an extended TableColumn. I suppose to be complete, I should create an interface that my subclass of TableColumn can implement; I can store my list of columns as a list of those instead of a list of a class.

I suppose I could (3) extend DefaultTableColumnModel, and build a vector of classes parallel to the vector of TableColumns. That might be better than storing it in the TableModel anyway.

But I thought I would ask for other suggestions. Has anyone else here implemented getColumnClass()?

rc
 
Bartender
Posts: 5167
11
Netbeans IDE Opera Java
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator

Ralph Cook wrote:I could extend TableColumn so that it had a "most specific superclass" stored for it; however, DefaultTableColumnModel stores its list of columns as a Vector<TableColumn>, so I can't store subclasses of TableColumn there (if you aren't familiar with generics, take my word for it or look it up).


Huh? Generics doesn't preclude adding a subclass of the Type. More specifically, run this code and see for yourself.
 
Sheriff
Posts: 22783
131
Eclipse IDE Spring VI Editor Chrome Java Windows
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
I think Ralph means that you cannot limit the contents of this list to instances of his sub class.

Ralph Cook wrote:My first thought was that TableColumn would have somewhere to store this column class, but it does not.


No, but it does have the getModelIndex() method that returns the column number of the matching TableModel. Through that you can get the column class, but I was surprised to see the column had no reference to the JTable, TableColumnModel or TableModel at all. That reference will have to go through your business logic.

You usually create a sub class of AbstractTableModel or DefaultTableModel to return something more specific than Object.class; I often use a switch statement.
 
Ralph Cook
Ranch Hand
Posts: 479
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator

Rob Spoor wrote:You usually create a sub class of AbstractTableModel or DefaultTableModel to return something more specific than Object.class; I often use a switch statement.



Well, yes I can do that, but it seems like such a kludge.

I have trouble understanding the conceptual model around JTable, possibly because no one documents conceptual models any more. From the TableColumn javadoc, we have:

javadoc wrote:A TableColumn represents all the attributes of a column in a JTable, such as width, resizibility, minimum and maximum width. In addition, the TableColumn provides slots for a renderer and an editor that can be used to display and edit the values in this column.



Except, evidently, the class associated with this column is NOT stored here.

So over in TableColumnModel, we have:

javadoc wrote:Defines the requirements for a table column model object suitable for use with JTable.



which really isn't very helpful. We see from its methods that it keeps a list of columns and retrieves individual columns, handles listener and selection things, and stores margins. Looks to me like this is a set of things that have to do with the collection of columns as they are in the table. I wouldn't think of this as the place to store a class associated with each column, and still wonder where they meant for that to be stored.

Now. I thought the whole point of the <? extends X> syntax in generics was to specify a collection of classes that are OR EXTEND another class. I thought, absent declaring your collection with that, that the system (compiler?) did prevent assigning a subclass of the object type into the collection. But you are correct: I added an extension to DefaultTableColumnModel to your code and called a method in it that accessed an extension of TableColumn, and it works. I'll have to go back now and see if it works with array lists as well as vectors. Thanks for pointing that out and completely confusing me on generics, which I thought I had (finally) figured out. (There is precious little conceptual explanation over there, also).

So that's opened up an option -- store my extension of TableColumn in the DefaultTableColumnModel.

Thanks to you both. I'm still looking for other ideas...

rc

p.s. if someone is interested in the generics question, I added a bit of code to satisfy myself that I could use it the way I would need to in this case
 
Rob Spoor
Sheriff
Posts: 22783
131
Eclipse IDE Spring VI Editor Chrome Java Windows
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator

Ralph Cook wrote:

Rob Spoor wrote:You usually create a sub class of AbstractTableModel or DefaultTableModel to return something more specific than Object.class; I often use a switch statement.



Well, yes I can do that, but it seems like such a kludge.

I have trouble understanding the conceptual model around JTable, possibly because no one documents conceptual models any more.


TableColumnModel only specifies which of the model's columns are displayed in the JTable. It uses TableColumn for that. You can set renderers / editors for TableColumn because those are not part of the model, only of the view (JTable). Anything related to the data, such as the column class, goes in the TableModel. The JTable and cohorts use that information for displaying the data.
 
Ralph Cook
Ranch Hand
Posts: 479
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
I'd like to check out one more set of things I think I've figured out about JTables and columns.

TableColumnModel and DefaultTableColumnModel store information about visible columns. JTable.removeColumn(), for instance, removes the column reference from the protected Vector tableColumns, declared in DefaultTableColumnModel.

I have a class that defines a column that might be displayed -- it has default width, header, renderer, etc., i.e., things the program needs to know in order to add it to the view. I guess I'm supposed to put a collection of those into TableModel, since TableModel.getColumnCount() returns "the number of columns in the model".

It also says that JTable uses this count to determine how many columns to display by default. Can I override that default? If I have 10 columns and want to display 4 of them initially, how do I have the JTable do that instead of displaying 10? Surely they didn't construct this so that I have to have it display 10 and then remove 6.

rc
 
Consider Paul's rocket mass heater.
reply
    Bookmark Topic Watch Topic
  • New Topic