I am using a custom JComboBox as a cell editor in a JTable. When the users gets to the cell using keyboard controls it tries to open the popup. This causes the following error:
java.awt.IllegalComponentStateException: component must be showing on the screen to determine its location
at java.awt.Component.getLocationOnScreen_NoTreeLock(Component.java:1964)
at java.awt.Component.getLocationOnScreen(Component.java:1938)
at javax.swing.JPopupMenu.show(JPopupMenu.java:887)
at javax.swing.plaf.basic.BasicComboPopup.show(BasicComboPopup.java:191)
at javax.swing.plaf.basic.BasicComboBoxUI.setPopupVisible(BasicComboBoxUI.java:859)
at javax.swing.JComboBox.setPopupVisible(JComboBox.java:796)
I have seen some articles stating that this is a known problem and the solution is to set:
comboBox.putClientProperty("JComboBox.isTableCellEditor", Boolean.TRUE);
This however does not help. What is this supposed to do anyways?
All the threads and articles I have read about this are very vague about the nature of the problem.
Does anyone have any insight into the nature of why this problem occurs? My combobox is very custom so it would help to understand the basis of the problem so I can fix the code.
This is triggered on a focus gained event on the combo box which is captured and call setPopupVisible(true);
public void focusGained(java.awt.event.FocusEvent e)
{
//if focus is gained then make sure we show the popup if it is suppose to be visible
setPopupVisible(true);
//and highlight the selected text if any
comboTextEditor.setCaretPosition(comboTextEditor.getText().length());
comboTextEditor.moveCaretPosition(0);
}
By the way I get the same results in Java 1.7_40 as Java 1.6_45
Full Stack Trace:
Exception in thread "AWT-EventQueue-1" java.awt.IllegalComponentStateException: component must be showing on the screen to determine its location
at java.awt.Component.getLocationOnScreen_NoTreeLock(Component.java:1964)
at java.awt.Component.getLocationOnScreen(Component.java:1938)
at javax.swing.JPopupMenu.show(JPopupMenu.java:887)
at javax.swing.plaf.basic.BasicComboPopup.show(BasicComboPopup.java:191)
at javax.swing.plaf.basic.BasicComboBoxUI.setPopupVisible(BasicComboBoxUI.java:859)
at javax.swing.JComboBox.setPopupVisible(JComboBox.java:796)
at com.mbs.generic.view.swing.combobox.AutoCompleteComboBox$1.focusGained(AutoCompleteComboBox.java:185)
at java.awt.AWTEventMulticaster.focusGained(AWTEventMulticaster.java:203)
at java.awt.Component.processFocusEvent(Component.java:6179)
at java.awt.Component.processEvent(Component.java:6046)
at java.awt.Container.processEvent(Container.java:2039)
at java.awt.Component.dispatchEventImpl(Component.java:4653)
at java.awt.Container.dispatchEventImpl(Container.java:2097)
at java.awt.Component.dispatchEvent(Component.java:4481)
at java.awt.KeyboardFocusManager.redispatchEvent(KeyboardFocusManager.java:1848)
at java.awt.DefaultKeyboardFocusManager.typeAheadAssertions(DefaultKeyboardFocusManager.java:901)
at java.awt.DefaultKeyboardFocusManager.dispatchEvent(DefaultKeyboardFocusManager.java:513)
at java.awt.Component.dispatchEventImpl(Component.java:4525)
at java.awt.Container.dispatchEventImpl(Container.java:2097)
at java.awt.Component.dispatchEvent(Component.java:4481)
at java.awt.EventQueue.dispatchEventImpl(EventQueue.java:648)
at java.awt.EventQueue.access$000(EventQueue.java:84)
at java.awt.EventQueue$1.run(EventQueue.java:607)
at java.awt.EventQueue$1.run(EventQueue.java:605)
at java.security.AccessController.doPrivileged(Native Method)
at java.security.AccessControlContext$1.doIntersectionPrivilege(AccessControlContext.java:87)
at java.security.AccessControlContext$1.doIntersectionPrivilege(AccessControlContext.java:98)
at java.awt.EventQueue$2.run(EventQueue.java:621)
at java.awt.EventQueue$2.run(EventQueue.java:619)
at java.security.AccessController.doPrivileged(Native Method)
at java.security.AccessControlContext$1.doIntersectionPrivilege(AccessControlContext.java:87)
at java.awt.EventQueue.dispatchEvent(EventQueue.java:618)
at java.awt.EventDispatchThread.pumpOneEventForFilters(EventDispatchThread.java:269)
at java.awt.EventDispatchThread.pumpEventsForFilter(EventDispatchThread.java:184)
at java.awt.EventDispatchThread.pumpEventsForHierarchy(EventDispatchThread.java:174)
at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:169)
at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:161)
at java.awt.EventDispatchThread.run(EventDispatchThread.java:122)
thanks
I second (third? fourth?) everyone asking for a pared-down example of a table using your custom combobox any maybe a bit of the code from the combobox itself, but just to take a stab at it anyway...have you tried making a customized version of EditorDelegate to go with your other custom code and moving the code for showing the popup from
focusGained()
into your delegate'sstartCellEditing()
method?If you embed your instruction inside a try .. catch instruction , your program will run without problems:
Popups like the pulldown in a JComboBox tend to have edge cases for event handling order because they are not geometrically nested inside their ancestors in the component hierarchy. In your case, you are causing the box's focus handler to show the pulldown. To do this it needs the box to be already located on the screen, but it's not.
The solution is almost certainly to defer showing the pulldown until all the events that will make the box visible have been processed. I had a similar (though not exactly the same) problem and was able to resolve it in this manner. Happily there is a Swing utility function that does the trick. Try wrapping the body of the focus gained handler in
invokeLater
and aRunnable
:The
invokeLater
puts a new message containing theRunnable
at the end of the queue, i.e. after all the existing ones. ThatRunnable
is executed only when the message makes it to the head, after all those other messages have been processed. This is exactly what you want.First, let me explain what
comboBox.putClientProperty("JComboBox.isTableCellEditor", Boolean.TRUE);
does. Normally, hoovering the mouse over an item or pressing the arrow keys on the keyboard will cause the selection of items on theJComboBox
immediately. Since selection events from theJComboBox
will cause the cell edit process to stop, this behavior is not suitable for table cells. So when setting this special client property items will be shown selected inside the popup list but not set on theJComboBox
yet. Only committed items (via click or Enter key) will change the selected item on theJComboBox
causing the end of the edit then. At least, this holds forBasicLookAndFeel
and its derivatives.The problem you have is completely different. As the exception message and the stack trace clearly say, the look and feel tries to open the
JPopupMenu
associated with theJComboBox
(as you requested) but it can’t determine the on-screen location for the popup menu because yourJComboBox
is not shot showing on the screen. The reason why it wants the location of theJComboBox
is that it opens the new window relative to theJComboBox
.The remaining question is why you received a
focusGained
from aJComboBox
that is not showing on the screen (or why you thought you did).