Java Swing : How to invoke stopCellEditing() before TreeListeners:valueChanged?
Asked Answered
F

2

3

This is a follow-up to these earlier questions:

When I use the terminateEditOnFocusLost property, like below, my CellEditor correctly stops editing when the table loses focus:

jtable.putClientProperty("terminateEditOnFocusLost", Boolean.TRUE);

It also works with my JButtons. The stopCellEditing() method is called for my TableCellEditor before the button press action is processed. But when I use it with a JTree, and the tree selection changes, the TreeSelectionListener.valueChanged method is called before stopCellEditing().

Does any one know if there is a way to force stopCellEditing() to be invoked first, or should I just make up some work-around for this issue?

Forenamed answered 14/8, 2009 at 8:55 Comment(0)
F
1

JTree does not have similar client property in Swing. But JXTree, a derived class from JTree, in SwingX does: invokeStopEditing.

If you can't use SwingX, you can always look at the source code of JXTree and see how this StopEditing mecanism works: JXTree SwingX 1.0 API Documentation and Javadoc (go to Source tab)

Specially, starting from line 974, a listener is created to monitor "permanentFocusOwner" property change on the KeyboardFocusManager etc...

Foundry answered 29/9, 2009 at 19:1 Comment(0)
G
0

I am not quite sure I understand your question with regards to the TreeSelectionListener and how it relates to the timing stopCellEditing() method being called. Are you creating a custom TreeCellEditor? If so, some more info on the setup of this editor would be useful.

However, you also referenced an earlier item which pertained to cell editing on a JTable, its loss of focus to an outside component, and the affect of this on the editing cell. I have taken that as a hint that you would like a similiar solution for JTree...


As noted, JTree does not implement the handling of the property for "terminateEditOnFocusLost" out of the box. This doesn't mean that you can do it yourself.

Looking at the code for JTable, it is pretty straight forward. A class is put together whose only job is to identify if the JTree still has focus when there is a focus change, and if not, it calls stopEditing() and if that fails it calls cancelEditing(). Here it is, adapted for a tree:

class CellEditorRemover implements PropertyChangeListener {
    KeyboardFocusManager focusManager;
    public CellEditorRemover(KeyboardFocusManager fm) {
        this.focusManager = fm;
    }

    public void propertyChange(PropertyChangeEvent ev) {
        if (!tree.isEditing() || 
          tree.getClientProperty("terminateEditOnFocusLost") != Boolean.TRUE) 
        {
          return;
        }

        Component c = focusManager.getPermanentFocusOwner();
        while (c != null) {
            if (c == tree) { // focus remains inside the tree
                return;
            } else if ((c instanceof Window)
                        || (c instanceof Applet && c.getParent() == null)) 
            {
                if (c == SwingUtilities.getRoot(tree)) {
                    if (!tree.getCellEditor().stopCellEditing()) {
                        tree.getCellEditor().cancelCellEditing();
                    }
                }
                break;
            }
            c = c.getParent();
        }
    }
}

You will note that your tree has to be accessible somehow to this class. There are a couple setup calls to perform to make this work:

tree.putClientProperty("terminateEditOnFocusLost", Boolean.TRUE);
KeyboardFocusManager fm = 
                KeyboardFocusManager.getCurrentKeyboardFocusManager();
editorRemover = new CellEditorRemover(fm);
fm.addPropertyChangeListener("permanentFocusOwner", editorRemover);

This should have the added benefit of making your JTree behave the same way that your JTable behaves when you press a JButton.

Graduated answered 4/10, 2009 at 2:9 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.