簡體   English   中英

jcombobox作為單元格編輯器java.awt.IllegalComponentStateException:必須在屏幕上顯示組件以確定其位置

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

我使用自定義JComboBox作為JTable中的單元格編輯器。 當用戶使用鍵盤控件進入單元格時,它會嘗試打開彈出窗口。 這會導致以下錯誤:

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)

我看過一些文章說這是一個已知問題,解決方法是設置:

    comboBox.putClientProperty("JComboBox.isTableCellEditor", Boolean.TRUE);

但這並沒有幫助。 無論如何這應該做什么?

我讀過的關於這個的所有主題和文章對於問題的本質都非常模糊。

有沒有人對這個問題出現的原因有什么了解? 我的組合框是非常自定義的,所以它有助於理解問題的基礎,所以我可以修復代碼。

這是在捕獲的組合框上的焦點獲取事件上觸發並調用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);
 }

順便說一句,我在Java 1.7_40中獲得與Java 1.6_45相同的結果

完整堆棧跟蹤:

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)

謝謝

首先,讓我解釋一下comboBox.putClientProperty("JComboBox.isTableCellEditor", Boolean.TRUE); 確實。 通常,將鼠標懸停在某個項目上或按下鍵盤上的箭頭鍵將立即導致選擇JComboBox上的項目。 由於來自JComboBox選擇事件將導致單元格編輯過程停止,因此此行為不適用於表格單元格。 因此,當設置此特殊客戶端屬性項時,將在彈出列表中顯示選中但尚未在JComboBox上設置。 只有提交的項目(通過單擊或Enter鍵)將更改JComboBox上的選定項目,然后導致編輯結束。 至少,這適用於BasicLookAndFeel及其衍生產品。

你遇到的問題完全不同。 由於異常消息和堆棧跟蹤清楚地說明,外觀嘗試打開與JComboBox關聯的JPopupMenu (如您所請求的)但它無法確定彈出菜單的屏幕位置,因為您的JComboBox未被拍攝顯示在屏幕上。 它想要JComboBox的位置的原因是它打開了相對於JComboBox的新窗口。

剩下的問題是為什么你從一個未在屏幕上顯示的JComboBox (或者你認為你做過的原因)收到了focusGained

類似於JComboBox中的下拉列表的彈出窗口往往具有事件處理順序的邊緣情況,因為它們在幾何上沒有嵌套在組件層次結構中的祖先中。 在您的情況下,您正在使框的焦點處理程序顯示下拉。 要做到這一點,它需要盒子已經位於屏幕上,但事實並非如此。

解決方案幾乎肯定是推遲顯示下拉,直到所有可以使框可見的事件都被處理完畢。 我有一個類似的(雖然不完全相同)問題,並能夠以這種方式解決它。 令人高興的是,有一個Swing實用程序功能可以解決問題。 嘗試在invokeLaterRunnable包裝焦點獲取處理程序的主體:

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

invokeLater在隊列末尾放置一條包含Runnable新消息,即在所有現有消息之后 在處理完所有其他消息之后,只有當消息進入頭部時才執行Runnable 這正是你想要的。

我是第二個(第三個?第四個?)每個人都要求使用你的自定義組合框的一個表的簡化示例,可能是組合框本身的一些代碼,但無論如何只是為了刺它...你試過嗎?制作一個自定義版本的EditorDelegate與你的其他自定義代碼一起使用並將代碼顯示從focusGained()到你的委托的startCellEditing()方法?

如果你在try .. catch指令中嵌入你的指令,你的程序將運行沒有問題:

SwingUtilities.invokeLater(new Runnable(){

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

                          }
                 }); 

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM