jcombobox as cell editor java.awt.IllegalComponentStateException: component must be showing on the screen to determine its location

女生的网名这么多〃 提交于 2019-12-01 20:50:38

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 the JComboBox immediately. Since selection events from the JComboBox 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 the JComboBox yet. Only committed items (via click or Enter key) will change the selected item on the JComboBox causing the end of the edit then. At least, this holds for BasicLookAndFeel 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 the JComboBox (as you requested) but it can’t determine the on-screen location for the popup menu because your JComboBox is not shot showing on the screen. The reason why it wants the location of the JComboBox is that it opens the new window relative to the JComboBox.

The remaining question is why you received a focusGained from a JComboBox that is not showing on the screen (or why you thought you did).

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 a Runnable:

void focusGained() {
  SwingUtilities.invokeLater(new Runnable() { 
    ... focus gained body including show of pulldown menu here ... 
  });
}

The invokeLater puts a new message containing the Runnableat the end of the queue, i.e. after all the existing ones. That Runnable 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.

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's startCellEditing() method?

Donata Savini

If you embed your instruction inside a try .. catch instruction , your program will run without problems:

SwingUtilities.invokeLater(new Runnable(){

                        public void run()
                        {
                        try {
                        tInput.putClientProperty("JComboBox.isTableCellEditor", Boolean.TRUE);
                        tInput.showPopup();
                        }
                        catch   (IllegalComponentStateException e) {
                                return;
                                }

                          }
                 }); 
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!