Java Forum / General / January 2006
Swing - JTable, CellEditors and terminateEditOnFocusLost
dbaldes - 09 Jan 2006 09:15 GMT Hello,
I have a JTable with some custom editors. I set the "terminateEditOnFocusLost" property to have editors get removed properly when the user "leaves" the table. The problem arises when the user is editing a cell of the table and then clicks on another cell to edit that one:
- editing of the cell currently being edited is stopped (good) - the editor of the new cell is loaded (getEditorComponent called) (good) - JTable loses focus for some reason to somewhere (probably bad) - JTable stops editing of the newly clicked cell (due to terminateEditOnFocusLost i guess) (bad)
So the user has to click a second time on the new cell to edit it, cause the editor was stopped right after being loaded on the first click..
Without "terminateEditOnFocusLost" the behaviour is also strange: on most Editors (simple text fields f.e.) it works well (problem described above does not arise) , but on a custom ComboBox editor the combobox pops up and closes again on the first click, BUT only when the cell editor used before was also the combobox editor.. so the user has to click a second time on the combobox to get the drop down list. When the user was editing another column (with other editor) before, the combobox pops up its drop down list and stays open on the first click as I expect it to.
What i want is: 1. the behaviour of terminateEditOnFocusLost without editors being removed when i click to edit a cell and 2. the combobox to pop up and stay open on 1st click in any case
I already tried overriding "shouldSelectCell" in the editors (which is not called any more, i read somewhere) because I suspected it to be related to focusing, and messing around with JTable.requestFocus, and the "focusable" property of the JTable is true - I did not get it to work properly up to now.
Can you help me with this problem?
Thanks in advance!
Regards, Daniel
zero - 09 Jan 2006 13:24 GMT > Hello, > [quoted text clipped - 41 lines] > Regards, > Daniel Do you have an online example that we could experiment with, and a short, compilable example (see http://www.mindprod.com/jgloss/sscce.html)
 Signature Beware the False Authority Syndrome
dbaldes - 09 Jan 2006 15:55 GMT Hi,
"unfortunately" i did not manage to reproduce the odd behaviour with the editors being removed im my sscce, but the combobox problem (described in paragraph "Without terminateEditOnFocusLost") arises here (with and without that property set). I will further investigate and try to reproduce the problem with editors being removed; In the meantime the following serves as sample for the ComboBox problem (which might be in some way related to the editors-being-removed-problem).
How to reproduce the problem with the sample code:
1. click on cell with "ab" in it -> combobox appears and pops open 2. select some value -> combobox closes its dropdown and displays new value 3. click on cell with "bb" in it -> new combobox appears, but is closed (i do not see the box pop open and close again; i think it is due to the example running faster due to the rather simple list content)
Whenever the combobox editor is active, clicking on another cell with the combobox editor gives the described behaviour. When another or no editor is active, the combobox pops open as it is supposed to.
any help is greatly appreciated.
---8X------------------------------------- import java.awt.BorderLayout; import java.awt.Component;
import javax.swing.*; import javax.swing.table.TableCellEditor;
public class TestMain {
public static void main(String[] args) { JTable table = new JTable( new String[][] { { "aa", "ab" }, { "ba", "bb" } }, new String[] { "A", "B"} ); table.putClientProperty("terminateEditOnFocusLost", Boolean.TRUE);
table.getColumnModel().getColumn(1).setCellEditor( new CustomEditor());
JFrame frame = new JFrame(); frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); frame.getContentPane().add(table, BorderLayout.CENTER); frame.getContentPane().add(new JTextField(), BorderLayout.SOUTH); frame.setSize(400,300); frame.setVisible(true); }
private static class CustomEditor extends AbstractCellEditor implements TableCellEditor {
private JComboBox cbComponent;
public CustomEditor() { cbComponent = new JComboBox(new String[] { "xx", "yy", "zz" } ); }
public Component getTableCellEditorComponent(JTable table, Object value, boolean isSelected, int row, int column) { return cbComponent; }
public Object getCellEditorValue() { return cbComponent.getSelectedItem(); } } }
dbaldes - 09 Jan 2006 16:08 GMT Hi again,
I just managed to reproduce the problem. The difference of the following code to the example above is that the ComboBox is inside a JPanel, and the JPanel is returned as editor (i do this to get the combobox centered vertically in higher rows in my application).
Repeat the steps in the posting before to reproduce the problem: Clicking on a combobox cell (here the rightmost column) when a ComboBox is already open results in the new editor being loaded, stopped and removed immediately.
Maybe the Table passes focus to the JPanel, the panel then passes focus to the ComboBox and the JTable then deems the focus to be lost?
------8X----------------------------------- import java.awt.BorderLayout; import java.awt.Component;
import javax.swing.*; import javax.swing.table.TableCellEditor;
public class TestMain {
public static void main(String[] args) {
JTable table = new JTable( new String[][] { { "aa", "ab" }, { "ba", "bb" } }, new String[] { "A", "B"} ); table.putClientProperty("terminateEditOnFocusLost", Boolean.TRUE);
table.getColumnModel().getColumn(1).setCellEditor( new CustomEditor());
JFrame frame = new JFrame(); frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); frame.getContentPane().add(table, BorderLayout.CENTER); frame.getContentPane().add(new JTextField(), BorderLayout.SOUTH); frame.setSize(400,300); frame.setVisible(true); }
private static class CustomEditor extends AbstractCellEditor implements TableCellEditor {
private JPanel panel; private JComboBox cbComponent;
public CustomEditor() { panel = new JPanel(new BorderLayout()); cbComponent = new JComboBox(new String[] { "xx", "yy", "zz" } ); panel.add(cbComponent, BorderLayout.CENTER); }
public Component getTableCellEditorComponent(JTable table, Object value, boolean isSelected, int row, int column) { return panel; }
public Object getCellEditorValue() { return cbComponent.getSelectedItem(); } } }
Vova Reznik - 09 Jan 2006 17:04 GMT > private static class CustomEditor > extends AbstractCellEditor > implements TableCellEditor { Did you find that your CustomEditor implements CellEditor twice? As sub of AbstractCellEditor and sub of TableCellEditor.
Try this: private static class CustomEditor extends DefaultCellEditor {
private JPanel panel; private static final JComboBox cbComponent = new JComboBox(new String[] { "xx", "yy", "zz" });
public CustomEditor() { super(cbComponent); panel = new JPanel(new BorderLayout()); panel.add(cbComponent, BorderLayout.CENTER); }
public Component getTableCellEditorComponent(JTable table, Object value, boolean isSelected, int row, int column) { return panel; }
public Object getCellEditorValue() { return cbComponent.getSelectedItem(); } }
dbaldes - 09 Jan 2006 17:21 GMT Hi,
it does not implement it twice. AbstractCellEditor implements CellEditor, and my Subclass implements remaining methods of TableCellEditor. This works well and is not related to the problem. Your code does not change the behaviour (it just adds useless functionality to the editor).
zero - 09 Jan 2006 22:50 GMT "dbaldes" <daniel.baldes@gmail.com> wrote in news:1136822935.645822.196620 @g47g2000cwa.googlegroups.com:
> Clicking on a combobox cell (here the rightmost column) when a ComboBox > is already open results in the new editor being loaded, stopped and > removed immediately. Ok, I think I have an acceptable solution.
Your main problem is that the editing is never actually stopped, because your CustomEditor never calls fireEditingStopped. You could add this in an itemListener or actionListener on the combo box, but those both have flaws (specifically when opening and closing the combo box without changing the selected value). The solution is to use a PopupMenuListener.
Add this to CustomEditor's constructor:
cbComponent.addPopupMenuListener(new PopupMenuListener() { public void popupMenuCanceled(PopupMenuEvent e) { fireEditingCanceled(); }
public void popupMenuWillBecomeInvisible(PopupMenuEvent e) { fireEditingStopped(); }
public void popupMenuWillBecomeVisible(PopupMenuEvent e) { } });
This code will cancel or stop the editing when appropriate.
I believe you don't need the terminateEditOnFocusLost property, but do some testing to be sure.
 Signature Beware the False Authority Syndrome
zero - 09 Jan 2006 22:56 GMT > Your main problem is that the editing is never actually stopped, > because your CustomEditor never calls fireEditingStopped. btw, all these problems are caused by the fact that you use the same CustomEditor for every cell in the column, and this CustomEditor re-uses the same JComboBox. If you would have a separate instance of CustomEditor for each cell, or recreate the JComboBox, I think you would have far less problems. But of course this does use more memory.
 Signature Beware the False Authority Syndrome
dbaldes - 10 Jan 2006 08:15 GMT Hi,
the default implementation of AbstractCellEditor calls fireEditingStopped() (and cancelled). My "true" application does it itself. (on stopCellEditing/cancelCellEditing, which is called by the table implementation; those methods are called when i leave the editing cell) Reusing Components is the intention of the whole TableCellEditor/Renderer model, i think..
But your code resolved the problem for me, so thanks a lot!
Regards, Daniel
dbaldes - 10 Jan 2006 08:20 GMT Hi, erm, wait,
it solves the problem for my combobox editors, which is a great step in the right direction, but... I also have other editos (textfield, lists..), so if anyone knows a more general solution I would be glad.
I'll try to add listeners and call fireEditingStopped/Cancelled myself, but I think there should be a way which works with the default behaviour (table implementation calls editor.stopCellEditing(), editor calls fireEditingStopped() ..)
thanks in advance..
Daniel
Free MagazinesGet these publications absolutely FREE for up to 12 months. There are no hidden fees and no obligation. Simply choose a title, complete the application form and submit it. Read more ...
|
|
|