Skip to main content

About JXTable sort

19 replies [Last post]
qiyadeng
Offline
Joined: 2005-10-23

I use JXTable sort function.

but i found a problem..

Afert sorting,I use dealTableMode.getSelectRow();the rows I select is not equal with the rows i get.

why?please give me a help.Thanks.

Message was edited by: qiyadeng

Reply viewing options

Select your preferred way to display the comments and click "Save settings" to activate your changes.
cupofjoe
Offline
Joined: 2003-08-05

So my hack blows up when you add a selection listener.

The internal code translates behind the scenes. Here is the stack trace:

Exception in thread "AWT-EventQueue-0" java.lang.ArrayIndexOutOfBoundsException: -1
at org.jdesktop.swingx.decorator.ShuttleSorter.mapTowardModel(ShuttleSorter.java:101)
at org.jdesktop.swingx.decorator.Filter.convertRowIndexToModel(Filter.java:115)
at org.jdesktop.swingx.decorator.FilterPipeline.convertRowIndexToModel(FilterPipeline.java:430)
at org.jdesktop.swingx.JXTable.convertRowIndexToModel(JXTable.java:1334)
at net.java.dev.tframe.swing.TTable.getSelectedRow(TTable.java:76)
at com.wachovia.cib.ac.gui.actool.panel.ReportPanel$3.valueChanged(ReportPanel.java:164)

getSelectedRow [b]CAN NOT[/b] return the translated value as shown here.

Cheers,
Ed

PS
OK...
You were right. Just call me the guy who 'runs with scissors' ;-)

cupofjoe
Offline
Joined: 2003-08-05

I ended up doing this instead. It seems to work OK and I like it MUCH better. It keeps all of my translation code in one place.

If I don't do it this way I have to translate every time I use an instance which is annoying.

This current feature limits me to only use Java 1.6.

/**
* Simple helper method that makes it easy to get what you want.
*
* Offers no value for view and just hides translation logic if
* table is sorted.
*
* enum options are: INDEX.VIEW or INDEX.MODEL
* VIEW will return the Table index for this row. It WILL change on a sort. ;-)
* MODEL is the model index regardless of the SORT state of the Table View
*
* @param perspective INDEX
* @return int
*/
public int getSelectedRow(INDEX perspective)
{
int viewRow = getSelectedRow();
switch (perspective)
{
case VIEW:
return viewRow;
case MODEL:
return this.convertRowIndexToView(viewRow);
default:
throw new IllegalStateException("This should never happen.");
}
}

cupofjoe
Offline
Joined: 2003-08-05

I wished I would have never posted to this thread. ;-)

Bug in my last message. The MODEL switch block should use this method instead:
convertRowIndexToModel(int viewRowIndex)

Cheers,
cupofjoe

cupofjoe
Offline
Joined: 2003-08-05

I tested it and it works with no errors. ;-)

The point I'm trying to address is what I consider a "logic box" of people who are producers of an API versus consumers of the API.

If you want to control the view you add a TableRenderer to custom paint your cells.

What every Swing developer needs is a way to go from the model to the JTable and vice-versa.

Why put extra burden on the caller? Why make it more complicated? At the Java One FireSide chat two years ago I heard Gosling and others say they were going to work on making things simpler to work with.

A JTable has the following three internal instance variable:

protected TableModel dataModel;
protected TableColumnModel columnModel;
protected ListSelectionModel selectionModel;

Why force the caller to do 'conversion' calls when ALL of the conversion is INTERNAL to the JTABLE?

BTW

My code above for JTable works with no errors. Honest...
If I hit an error I will let you know and post it here.

Cheers,
Ed

cupofjoe
Offline
Joined: 2003-08-05

I had to remove this method:

[b]public int convertRowIndexToModel(int x)[/b]
{
throw new RuntimeException("This method is not needed.\nThe DEFAULT behaivor of TTable.getSelectedRow() translates internally now.");
}

After this tweak I've had no problems. The code is cleaner and easier to read .
Your concern about me changing the behavior of a public method is also valid.

I really just need to create two methods that do this and give them a better naming convention.

Since JTable/JXTable contains all of the data members needed this is simple.

When I read the link from 2005 I was sad to see that someone suggested ripping out all of the Swing data models to use collections and just toss the index issues out.

That is a huge undertaking but it would really make everyone's job easier IMHO.

Thanks for feedback.

Cheers,
Ed

kschaefe
Offline
Joined: 2006-06-08

Um, OK. Wasn't trying to get into a debate, just an explanation. SwingX is designed to extend Swing components, being a Sun-sponsored project. That being said, you're unlikely to get such a fundamental change in SwingX, in part because it would break the contract establish by the JTable documentation.

Of course, you're welcome to do what you like in your own code.

Karl

cupofjoe
Offline
Joined: 2003-08-05

Karl,

I guess I'm just having issues dealing with change. :-)

The only reason I've ever used getSelectedRow() in JTable was so I could get to the underlying data model and grab an object that got selected in the view.

I just don't understand why things have to always be so hard. Look at the example here:
http://java.sun.com/docs/books/tutorial/uiswing/components/table.html

table.getSelectionModel().addListSelectionListener(
new ListSelectionListener() {
public void valueChanged(ListSelectionEvent event) {
int viewRow = table.getSelectedRow();

Now with the new JTable features I have to juggle two sets of indexes and constantly translate them when all I need are two things:
1. Pull from the view info to get the object from the data model
2. For an object in the data model get info to select it in the view

It also gets very confusing when your in the TableModel versus when your in the JTable code.

I wrote code around TableSorter and thought all my worries would be over once I got the NEW JXTable.

Sigh...
So just like everything else. For me to make it simple to work with I have to write a helper class and keep it around to make things easier to work with.

I still think there should be two methods built into JTable that meet the two bullets listed above. ;-)

Cheers,
Ed

cupofjoe
Offline
Joined: 2003-08-05

BTW

Just to clarify things. I'm aware that there are two models wrapped within the JXTable or TableSorter implementation.

The point I was trying to make is if 'internally' JXTable or TableSorter needs the info then make the method 'private'.

I only see two things here that the public API needs to provide:
Take an object in the tabel model and force it to be selected in the current table view.
Given a selected row in the table VIEW get the object from the model.

Shouldn't it be an obvious refactoring smell that the old class had one method and now I need extra 'utility methods' to translate between the TableModel I gave JXTable and the TableModel it uses for the view?

Heck, just give me a method to get directly to the underlying object from the view and throw out the entire getRow[index] concept. ;-)

Not that I [b]HAVE [/b] a strong opinion on this or anything. I'm totally neutral on the topic. :-)

Cheers,
Ed

qiyadeng
Offline
Joined: 2005-10-23

Thank you.Kleopatra !

solve this problem.

Kleopatra

jdnc-interest@javadesktop.org schrieb:
> I use JXTable sort function.
>
> but i found a problem..
>
> Afert sorting,I found user dealTableMode.getSelectRow();the rows I select is not equal with the rows i get.
>

There are two coordinate systems: model coordinates (used when querying
the TableModel) and view coordinates (used when querying the table).
Keep in mind that _everything_ coming from the table (such as selection
index f.i.) is in view coordinates. The table has methods to convert
to/from model indices (look for convertRowIndexToZZ).

Cheers
Jeanette

---------------------------------------------------------------------
To unsubscribe, e-mail: jdnc-unsubscribe@jdnc.dev.java.net
For additional commands, e-mail: jdnc-help@jdnc.dev.java.net

cupofjoe
Offline
Joined: 2003-08-05

Not to sound to stupid here. It looks like a lot of the authors of JXTable are highly skilled.

Why wouldn't you over-ride getSelectedRow() and getSelectedRows() to return the RIGHT values? :-)

It looks like the Table object is a little stupid when you have to help it translate something that contains it's own internal state.

int index = _queryTable.convertRowIndexToModel(_queryTable.getSelectedRow());
return _tableModel.getADO(index);

Cheers,
Ed

Kleopatra

jdnc-interest@javadesktop.org schrieb:
> Not to sound to stupid here. It looks like a lot of the authors of JXTable are highly skilled.
>

thanks for noticing

> Why wouldn't you over-ride getSelectedRow() and getSelectedRows() to return the RIGHT values? :-)
>

as often RIGHT is a matter of perspective: model coordinates are RIGHT
for models and view coordinates are RIGHT for .. well.. views. As the
table is a view, everything there is in view coordinates. _Really_
everthing, for consistency. It's easy enough for client code to use
utility methods if you need to convert often. On the other hand, your
code could query the table directly (as - see above - everything is in
view coordinates).

HTH
Jeanette

---------------------------------------------------------------------
To unsubscribe, e-mail: jdnc-unsubscribe@jdnc.dev.java.net
For additional commands, e-mail: jdnc-help@jdnc.dev.java.net

cupofjoe
Offline
Joined: 2003-08-05

Jeanette,

I had to add this code to the TableSorter for my simple GUI framework (TFrame).

/**
* Given the list of selected rows in a JTable convert that
* list to an array of indexes that match the model.
* This way if they sort the table we can still easily
* translate to the objects in the underlying table model.
*
* Ed Tidwell added 11/18/05
*
* @param tableRows int[]
* @return int[]
*/

I would hate to admit that the only regular issue QA usually gets me for is...
[i]"I sorted the table and double-clicked but the wrong value appeared"[/i]
[b]
It is WAY to easy to forget to call this method correctly. ;-)
That tells me that it is broken. IMHO[/b]

If an object has "getSelectedRow()" that breaks when that OBJECT changes state then it should fix the implementation.

I could easily wrap the JXTable object and over-ride the behavior. I just can't believe that something that simple isn't in the public API method.

Would anyone EVER want to call this method and NOT get the selected row? :-)

Is it that hard to do or is there something that will break if you fix this as suggested?

Cheers,
Ed

kschaefe
Offline
Joined: 2006-06-08

> I would hate to admit that the only regular issue QA
> usually gets me for is...
> [i]"I sorted the table and double-clicked but the
> wrong value appeared"[/i]
> [b]
> It is WAY to easy to forget to call this method
> correctly. ;-)
> That tells me that it is broken. IMHO[/b]
>
> If an object has "getSelectedRow()" that breaks when
> that OBJECT changes state then it should fix the
> implementation.
Well, there is an MVC-approach in the works here (sort of). With the J(X)Table as the view and the TableModel as, well, the model. The controller "class" is noticeably missing. This is the general problem with Swing, in that the controller functionality is often folded into the view. Hence, the table contains methods for translating model and view coordinates. In a true MVC approach, there would be a seperate class to handle this coordination.

While I sympathize with your situation, it's important to maintain the seperation of concerns that the MVC-esque approach is giving us. It sounds to me like you'd prefer to have the controller be seperate and able to manage the translation of the view and model. In that case, I'd create a TableContoller that takes a table and using the "controller" methods from the tables, provides the functionality that you're looking for. This would maintain the seperation, but provide a clearly delineated location for you to perform your conversions.

So, your example is concerning selected rows. The model has no idea what a selected row is, nor should it. The idea of being able to select a row is a completely view-related item. The view is also able to represent that data in any way it feels like, it's a view of the data. So the data can be presented in the view as sorted or filtered or as completely different data. That's what views do; they show things. Model only hold and maintain the integrity of the data. This means that all modifications to the data happen within the model. So, how do we get from one to the other? In true MVC, the controller would handle this corelation, however, it is done in the table's view in Swing with the convertX methods.

I know that this really doesn't "satisfy" the concern you have, but I hope my explanation helped.

Karl

cupofjoe
Offline
Joined: 2003-08-05

Imagine explaining the problem to a 5 year old. It should be that simple.
Let's not go into the MVC and how Swing only has a M - VC pattern on this one.

Come to think of it. I will just fix this in my version of JXTable. That way when I call the public method of getSelectedRows() in the VIEW-CONTROLLER. I don' t have to worry what state the table is in.

Problem solved.

I really didn't want a debate. I just thought this should be fixed.

Cheers,
Ed

cupofjoe
Offline
Joined: 2003-08-05

FYI

Here is the code...

Seems to work fine and I get to delete all of the utility translation code out of my application. ;-)

package net.java.dev.tframe.swing;

import org.jdesktop.swingx.JXTable;
import javax.swing.table.TableModel;
import javax.swing.table.TableColumnModel;
import javax.swing.ListSelectionModel;
import java.util.Vector;

/**
* Simple wrapper of JXTable to prevent the caller from having to use translation utilities.
* Ed Tidwell 7/18/2007
*/
public class TTable
extends JXTable
{
// wrap supported CTORs in parent object
public TTable()
{
super();
}

public TTable(TableModel dm)
{
super(dm);
}

public TTable(TableModel dm, TableColumnModel cm)
{
super(dm, cm);
}

public TTable(TableModel dm, TableColumnModel cm, ListSelectionModel sm)
{
super(dm, cm, sm);
}

public TTable(int numRows, int numColumns)
{
super(numRows, numColumns);
}

public TTable(Vector rowData, Vector columnNames)
{
super(rowData, columnNames);
}

public TTable(Object[][] rowData, Object[] columnNames)
{
super(rowData, columnNames);
}

/**
* Over-ride this method so it will ALWAYS translate from the JXTable internal
* data model used for sorting and filtering to the USER'S provided TableModel.
*
* This method WILL ALWAYS RETURN the bottom underlying TableModel and translates
* by default.
*
* @return int
*/
public int getSelectedRow()
{
return super.convertRowIndexToModel(super.getSelectedRow());
}

public int convertRowIndexToModel()
{
throw new RuntimeException("This method is not needed.\nThe DEFAULT behaivor of TTable.getSelectedRow() translates internally now.");
}
}

Kleopatra

Ed,

sorry for being blunt - but what you are doing is wrong, ehem WRONG!

It shouldn't even start-up (the conversion method is used internally),
and it's an absolute no-no to go inconsistent in an extension. With your
implementation

table.getValueAt(getSelectedRow(), somecolumn)

will blow for filtered/sorted tables. Might even be illegal if the model
row coordinate > view row count. There's a lot more arguments, too lazy
to repeat them here, so here's a link:

http://forums.java.net/jive/thread.jspa?messageID=59847&#59847

The discussion ended with a sound decision - no way (and no reason) to
change that, not in SwingX and neither in core Swing.

Jeanette

---------------------------------------------------------------------
To unsubscribe, e-mail: jdnc-unsubscribe@jdnc.dev.java.net
For additional commands, e-mail: jdnc-help@jdnc.dev.java.net

Kleopatra

oops, got the link wrong, trying again

http://forums.java.net/jive/thread.jspa?threadID=8701

Jeanette

---------------------------------------------------------------------
To unsubscribe, e-mail: jdnc-unsubscribe@jdnc.dev.java.net
For additional commands, e-mail: jdnc-help@jdnc.dev.java.net

cupofjoe
Offline
Joined: 2003-08-05

Thanks for the link. This was a great read. A few comments worth mentioning from the link you gave me are below. They only help VALIDATE what I'm trying to communicate. It didn't convince me to 'give in' to peer pressure. ;-)

Scott Violet --- This adds no end of confusion, even for us... It's so easy to forget to
do a conversion.

keithkml Re: Mustang feature: Table Sorting
Posted: May 5, 2005 10:25 AM in response to: Scott Violet

I think sorting should be done independently of the model - that is, 100% by the view, just like column reordering. JTable should support a concept of virtual and physical indices for both rows and columns. I believe this could be made transparent to current code by automatically converting from view to model and vice versa in the necessary cases.

Then, I think JTable needs a new API for controlling and monitoring sorting, as well as finding visual positions of elements and vice versa.