This is a follow-up to these earlier questions:
- How to stop editing with DefaultCellEditor when a separate JBtton is pressed
- Sun Bug 4724980: JTable: Add API to control what happens to edits when table loses focus.
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?
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...
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
.