[SWINGX-1555] JXTable: issues with resizing behaviour in horizontalScrollEnabled mode Created: 21/Mar/13  Updated: 21/Mar/13

Status: Open
Project: swingx
Component/s: Table
Affects Version/s: None
Fix Version/s: None

Type: Bug Priority: Major
Reporter: kleopatra Assignee: kleopatra
Resolution: Unresolved Votes: 0
Labels: None
Remaining Estimate: Not Specified
Time Spent: Not Specified
Original Estimate: Not Specified

Tags: JXTable, horizontalScrollEnabled

 Description   

overall requirements in http://stackoverflow.com/q/15499255/203657 (against JTable + custom code)

JXTable issues:

  • can't shrink last column
  • after shrinking any of the pre-last columns, extending that column again leads to showing up the scrollBar "too early", that is subsequent columns are not shrunken until they reach their respective pref (feels like a core issue?)





[SWINGX-1521] JTable, BooleanEditor: inconsistent background color Created: 11/Aug/12  Updated: 13/Aug/12  Resolved: 13/Aug/12

Status: Resolved
Project: swingx
Component/s: Renderer
Affects Version/s: 1.6.4
Fix Version/s: 1.6.5

Type: Bug Priority: Major
Reporter: kleopatra Assignee: kleopatra
Resolution: Fixed Votes: 0
Labels: None
Remaining Estimate: Not Specified
Time Spent: Not Specified
Original Estimate: Not Specified

Tags: BooleanRenderer, JXTable

 Description   

the background color is different when starting edit on a formerly unselected vs. selected row.

It's a core issue: in getXXEditorComponent, DefaultCellEditor with a JCheckBox as editing component queries the renderer for the same cell with the same parameters. At that time, the isSelected is false for an unselected row because the selection is updated after installing the editor (done in BasicTableUI adjustSelection)

Easiest option to fix would be to modify the isSelected param before calling super. Might be hard-coded true/false or query shouldSelect.

Usability issue: not-selecting the editor when the row is selected (and the other way round) is a stronger visual clue that editing is happening. Or make it configurable somehow?



 Comments   
Comment by kleopatra [ 13/Aug/12 ]

fixed by adjusting selected (to take into account shouldSelect) before passing to super

committed in revision #4231





[SWINGX-1520] row count returns cached value Created: 10/Aug/12  Updated: 16/Aug/12  Resolved: 16/Aug/12

Status: Resolved
Project: swingx
Component/s: Table
Affects Version/s: 1.6.4
Fix Version/s: 1.6.5

Type: Bug Priority: Major
Reporter: tbee Assignee: kleopatra
Resolution: Invalid Votes: 0
Labels: None
Remaining Estimate: Not Specified
Time Spent: Not Specified
Original Estimate: Not Specified

Tags: defaultsortcontroller, jxtable

 Description   

I have a JTableNavigator component that calls getRowCount on the table but on occasion gets the wrong value. After some researching I found that it get the value of cachedModelRowCount in DefaultSortController. This strange thing is; this happens without sorting, or more importantly filtering, being active. The situation is fairly complex, using asynchronous loading on tabs, so creating a simple example is quite complex. I've patched it by explicitly clearing the row sorter (setRowSorter(null)). Maybe an additional check if sorting or filtering is actually active should be added before using the cached value?



 Comments   
Comment by kleopatra [ 10/Aug/12 ]

hmm ... wouldn't it be you I would guess it to be an EDT problem

We should try to somehow reproduce it, or at least narrow it (would hate blind additional checks - that caching on SortController actually is a hack around super misbehaving, so adding yet another hack on top ... )

Only happens if a sorter is registered but nothing sorted nor filtered? When do you clear the sorter, after/during loading?

Comment by tbee [ 10/Aug/12 ]

Nah, this happily runs all inside the EDT. The easiest way would be to remote desktop show you

What happens is that the TableNavigator does a getRowCount, the JTable checks if a sorter is active (it is, SwingX's DefaultSortController), forwards the call to the sorter and returns the cached value. Which is 0 instead of the actual number of rows present in the model.

I extend JXTable with my own JTable class (which makes reproducing the problem even more simple) adding the MSAccess alike data entry functionality... Maybe I should first see if things need to be cleaned up there, chances are it is caused by something I setup; this inheritance has 'survived' years of SwingX versions. Never the less, fact is that getRowCount returns cachedRowCount, which value is incorrect. Somewhere in my usage the cache update logic misses a beat.

Comment by kleopatra [ 10/Aug/12 ]

(damned internet - lost my last coment

So here's a short version:

Sounds like the navigator queries the table before its internal state is completely updated.

See the core bug mentioned in the DefaultSortController java doc and the forum discussions around the fix in SwingX.

Could well be that you hit a corner case which isn't fully covered by the logic of the workaround. Hard to say without a test case

Comment by kleopatra [ 16/Aug/12 ]

here's a code snippet demonstrating what I mean:

    final DefaultTableModel model = new DefaultTableModel(5, 3);
    final JXTable table = new JXTable(model);
    final JTable core = new JTable(model);
    TableModelListener l = new TableModelListener() {
        
        @Override
        public void tableChanged(TableModelEvent e) {
            LOG.info("model/X/core: " + model.getRowCount() 
            // the following two lines are _illegal_
                    + "/" + table.getRowCount()
                    + "/" + core.getRowCount()
                    );
        }
    };
    model.addTableModelListener(l);
    Action action = new AbstractAction() {

        @Override
        public void actionPerformed(ActionEvent e) {
            model.addRow(new Object[] {null, null});
        }
        
    };
    new Timer(100, action).start();

As there is no guarantee to the sequence of notification, client code must not access notifier-dependent state of sister listeners. Core table's rowsorter accidentally has the same state (at the price of the core bug). The typical safe way to query sister listener's state is to invoke the access.

So tend to close this as invalid, lest you convince me that your code isn't violating the rule

Comment by tbee [ 16/Aug/12 ]

Coincidentally I've been looking into this just now, based on you second comment, and indeed is bar notified using a TableModelListener and then gets the row count. Exactly as you describe.

A discussion naturally is; how should anyone know that table.getRowCount() is depending on a sister listener (that was introduced somewhere in the not too distant past)? It seems to me that the call to table.getRowCount() or model.getRowCount() is valid for a table model listener to do. Is this caching introducing a dependency to a sister listener that should not be?

Comment by tbee [ 16/Aug/12 ]

And naturally the logical follow up; if a table model listener cannot get the row count by calling getRowCount(), where should it get that information from?

Comment by kleopatra [ 16/Aug/12 ]

It seems to me that the call to table.getRowCount() or model.getRowCount() is valid for a table model listener to do

the latter is always valid, the former only after the table (as sister listener) has updated its internal state completely. It's always valid to invoke the former, that is delay until the current event handling chain is ready. Which isn't new: from day zero the table itself has been listening to its model

It always was incorrect to access sister state that's potentially not yet updated, f.i. you wouldn't query the selection index in your tableModelListener. Same with model-related stuff.

Simply wrap the access into a SwingUtilities.invokeLater, that is and always has been the recommended way to handle those sister listener contexts. The new thingy is, that - with the advent of filtering - the rowCount belongs to the properties that are no longer safe to access before the table's internal update is ready.

Comment by tbee [ 16/Aug/12 ]

You are right, I'll change my code. Thanks for figuring this out.

Comment by kleopatra [ 16/Aug/12 ]

closing as invalid by consent with reporter

Thanks for bringing this up, so we can be sure





[SWINGX-1489] JXTable inside JInternalFrame doesn't show JComboBox editor without focusing table first Created: 04/Apr/12  Updated: 11/Apr/12  Resolved: 11/Apr/12

Status: Resolved
Project: swingx
Component/s: Table
Affects Version/s: 0.9.0, 0.9.1, 0.9.2, 0.9.3, 0.9.4, 0.9.5, 0.9.6, 0.9.7, 1.0, 1.6, 1.6.1, 1.6.2, 1.6.3
Fix Version/s: None

Type: Bug Priority: Major
Reporter: adrienclerc Assignee: kleopatra
Resolution: Won't Fix Votes: 0
Labels: None
Remaining Estimate: Not Specified
Time Spent: Not Specified
Original Estimate: Not Specified

Attachments: Java Source File TestBugJInternalFrame.java     File TestBugJInternalFrame.tar.bz2    
Tags: jinternalframe, jxtable

 Description   

Hi,

When you set a DefaultCellEditor with a JComboBox to a JXTable, there is an issue if this JXTable is inside a JInternalFrame.

Test project

You'll find as attached a test project created with Netbeans. Two frames are created. The first contains a panel with a JXTable and a JTable. The second contains a JInternalFrame within a JDesktopPane, in which the another instance of the same panel (with two tables) is added.
Both table have the same model, except for column name, in order to identify them.
Both table have two instances of the same default editor for Object class (i.e. for all cell) which is a DefaultCellEditor using a JComboBox with fixed values.

Test scenario

Now run the project, two frame should appears, and follow these instructions on both frame:

  1. Click on a cell of the JTable
  2. Click on a cell of the JXTable

In the first frame, when you click on a cell of the JXTable, the drop down menu should appear as expected.
In the second frame, it does not. You must click inside an empty space of the JXTable first, to focus it, and then in a cell to make the editor appears.

What goes wrong?

In short: the CellEditorRemover.
Long explanation. It seems that JInternalFrame switch the focus to the old focused component, before regiving it to the editor (JComboBox). But the CellEditorRemover cancels the edition as soon as the permanent focus owner doesn't belong to the JXTable. You can check this using this listener:

PropertyChangeListener pcl = new PropertyChangeListener() {

    @Override
    public void propertyChange(PropertyChangeEvent evt) {
        Object oldValue = evt.getOldValue();
        Object newValue = evt.getNewValue();
        if (newValue == null || ! JFrame.class.equals(newValue.getClass())) {
            int i = 1;
        }
        System.out.println(evt.getPropertyName() + " from "
                + (oldValue == null ? null : oldValue.getClass().getCanonicalName() + oldValue.hashCode())
                + " to "
                + (newValue == null ? null : newValue.getClass().getCanonicalName() + newValue.hashCode()));
    }
};

KeyboardFocusManager.getCurrentKeyboardFocusManager().addPropertyChangeListener("focusOwner", pcl);

Do you have any idea how to fix this annoying behavior?



 Comments   
Comment by kleopatra [ 08/Apr/12 ]

could you please attach a small test case (single file with around 50 lines should suffice) - no need for anything monstrous like a Netbeans (shudder project ..

Reading your description more thoroughly: could be that the different behaviour is due to the different default of termniateEditOnFocusLost (it's false for core and true for JXTable)

Thanks
Jeanette

Comment by kleopatra [ 09/Apr/12 ]

cant see a difference between core and xtable, using the core demo of the online tutorial:

    public static class MyInternalFrame extends JInternalFrame {
        static int openFrameCount = 0;
        static final int xOffset = 30, yOffset = 30;

        public MyInternalFrame() {
            super("Document #" + (++openFrameCount), 
                  true, //resizable
                  true, //closable
                  true, //maximizable
                  true);//iconifiable

            //...Create the GUI and put it in the window...
            add(createTable());
            //...Then set the window size or call pack...
            setSize(300,300);

            //Set the window's location.
            setLocation(xOffset*openFrameCount, yOffset*openFrameCount);
        }
        

        private JComponent createTable() {
            JTable table = openFrameCount < 2 ?
                    new JTable(new AncientSwingTeam()) :
                    new JXTable(new AncientSwingTeam());
            
            JComboBox combo = new JComboBox(new Object[] {1, 2, 3}); 
//            combo.setEditable(true);
            table.getColumnModel().getColumn(0).setCellEditor(new DefaultCellEditor(combo));
            return new JScrollPane(table);        
        }
    }

The dropdown doesn't open reliably in both, so pointing fingers to core and tending to close this ... modulo you convincing me

Cheers
Jeanette

Comment by adrienclerc [ 10/Apr/12 ]

Here is a single file with the code you expect.
Providing the full NB project was just a way to make it easily reproducible.

I'll search for the online tutorial to be able to run the full code you provided. Since the site change, it's a bit difficult to find those kind of resources

Comment by kleopatra [ 10/Apr/12 ]

meant the sun tutorial, very basic, unchanged for years

Thanks for the code, will give it a look asap, Jeanette

Comment by kleopatra [ 10/Apr/12 ]

as I suspected: it's a core issue related to terminateEditOnFocusLost. To verify, either disable on JXTable or enable on JTable (first makes the xTable as well-behaved as core - but loosing the natural auto-commit, second shows the issue in core as well):

// disable on xTable
jXTable.setTerminateEditOnFocusLost(false);
// or enable on core table
jTable.putClientProperty("terminateEditOnFocusLost", true);

Please file an issue in snoracle's bug-parade (nasty me

Meanwhile ... not sure if/how we can hack around, need to think a bit

Jeanette

Comment by adrienclerc [ 11/Apr/12 ]

Thanks for the advice, it could help us, at least to do this as a workaround.

However, the real question is: why the focus subsystem gives the focus to a different component when using JInternalFrame than JFrame? And why the focus is changed so often when using a JInternalFrame? This is weird.

I'll see if I have time to fill in a bug report in Oracle's one…

Comment by kleopatra [ 11/Apr/12 ]

just noticed that it seems to fixed in jdk7: kind of, the focus state still is a bit weird and the dropdown not opening reliably, but at least it goes into editing mode.

Could you verify this in your context?

Cheers
Jeanette

Comment by adrienclerc [ 11/Apr/12 ]

Indeed, using JRE 1.7.0_03-b04 fixed the issue. It is useless to report it, then.

However, I have now a huge task: how to upgrade everything I have to JRE7 smoothly

This issue can be closed if you have nothing to add.

Comment by kleopatra [ 11/Apr/12 ]

resolving as per discussion: it's a core issue which is fixed in jdk7

Thanks





[SWINGX-1396] JXTable fail to change boolean value Created: 25/Feb/11  Updated: 28/Feb/11  Resolved: 28/Feb/11

Status: Resolved
Project: swingx
Component/s: Table
Affects Version/s: 1.0, 1.6, 1.6.1, 1.6.2
Fix Version/s: None

Type: Bug Priority: Minor
Reporter: gervaisb Assignee: kleopatra
Resolution: Cannot Reproduce Votes: 0
Labels: None
Remaining Estimate: 1 hour
Time Spent: Not Specified
Original Estimate: 1 hour
Environment:

Windows 7, Windows XP. JDK 1.6_15 and 1.6_20 but not 1.5. (Other versions of Djdk 1.6 no tested)


Tags: Boolean, Column, JXTable, JXTable$BooleanEditor

 Description   

With a JXTable who contains editable Boolean columns. The editor cannot change the cell value. I have quickly wrote another TableCellEditor for this JXTable and he works. The only changes with yours is that I listen action on the checkbox to update a boolean.
Here is my editor (poorly writed) :

// ---------------------------------------------------------
private static class Editor extends DefaultCellEditor {

JCheckBox chk = null;
final boolean[] checked = new boolean[]

{true}

;

public Editor() {
super(new JCheckBox());
chk = (JCheckBox) getComponent();
chk.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e)

{ checked[0] = !checked[0]; }

});
}

@Override
public Object getCellEditorValue()

{ return checked[0]; }

@Override
public Component getTableCellEditorComponent(JTable table,
Object value, boolean isSelected, int row, int column)

{ JCheckBox chk =(JCheckBox) super.getTableCellEditorComponent(table, value, isSelected, row, column); checked[0] = ((Boolean) value).booleanValue(); chk.setSelected(checked[0]); return chk; }


}
// ------------------------------------------------------------



 Comments   
Comment by kleopatra [ 25/Feb/11 ]

can't reproduce - and the editor is the exact same as in a core JTable: a DefaultCellEditor vending a JCheckBox, the editor does all the wiring. There must be something else wrong in your code.

To verify that the default editors work smoothly in JXTable smoothly, run any of the visual tests containing a table with booleans, f.i. in JXTableVisualCheck.

Will close as worksforme - except you convince me with a small runnable example demonstrating the problem

Cheers
Jeanette

Comment by kleopatra [ 28/Feb/11 ]

closing a worksforme , please feel free to re-open with a short runnable example

Comment by gervaisb [ 28/Feb/11 ]

The bug has been discovered into our app (closed source) I'm going to write a code who reproduce the bug on my free time. Please be patient





Generated at Fri Aug 26 07:27:15 UTC 2016 using JIRA 6.2.3#6260-sha1:63ef1d6dac3f4f4d7db4c1effd405ba38ccdc558.