JButton的动作调用了focusLost事件.这怎么可能?

bar*_*jak 5 java swing action focus jbutton

我们的一位客户在我们的申请中报告了一个例外.问题是,我完全无法理解如何重现这个bug.

这是代码:

btn.addActionListener(new ActionListener() {
    @Override
    public void actionPerformed(ActionEvent e) {
        popup.show(btn, 3, btn.getHeight());
    }
});
Run Code Online (Sandbox Code Playgroud)

备注:

  • btn是类型的最终局部变量JButton.
  • popup是类型的最终局部变量JPopupMenu.

抛出以下异常:

java.awt.IllegalComponentStateException: component must be showing on the screen to determine its location
    at java.awt.Component.getLocationOnScreen_NoTreeLock(Unknown Source)
    at java.awt.Component.getLocationOnScreen(Unknown Source)
    at javax.swing.JPopupMenu.show(Unknown Source)
    at fr.def.iss.vd2.mod_site_watcher_gui.SiteElementPanel$4.actionPerformed(SiteElementPanel.java:117)
    at javax.swing.AbstractButton.fireActionPerformed(Unknown Source)
    at javax.swing.AbstractButton$Handler.actionPerformed(Unknown Source)
    at javax.swing.DefaultButtonModel.fireActionPerformed(Unknown Source)
    at javax.swing.DefaultButtonModel.setPressed(Unknown Source)
    at javax.swing.plaf.basic.BasicButtonListener.focusLost(Unknown Source)
    at java.awt.Component.processFocusEvent(Unknown Source)
    at java.awt.Component.processEvent(Unknown Source)
    at java.awt.Container.processEvent(Unknown Source)
    at java.awt.Component.dispatchEventImpl(Unknown Source)
    at java.awt.Container.dispatchEventImpl(Unknown Source)
    at java.awt.Component.dispatchEvent(Unknown Source)
    at java.awt.KeyboardFocusManager.redispatchEvent(Unknown Source)
    at java.awt.DefaultKeyboardFocusManager.typeAheadAssertions(Unknown Source)
    at java.awt.DefaultKeyboardFocusManager.dispatchEvent(Unknown Source)
    at java.awt.Component.dispatchEventImpl(Unknown Source)
    at java.awt.Container.dispatchEventImpl(Unknown Source)
    at java.awt.Component.dispatchEvent(Unknown Source)
    at java.awt.EventQueue.dispatchEventImpl(Unknown Source)
    at java.awt.EventQueue.access$000(Unknown Source)
    at java.awt.EventQueue$1.run(Unknown Source)
    at java.awt.EventQueue$1.run(Unknown Source)
    at java.security.AccessController.doPrivileged(Native Method)
    at java.security.AccessControlContext$1.doIntersectionPrivilege(Unknown Source)
    at java.security.AccessControlContext$1.doIntersectionPrivilege(Unknown Source)
    at java.awt.EventQueue$2.run(Unknown Source)
    at java.awt.EventQueue$2.run(Unknown Source)
    at java.security.AccessController.doPrivileged(Native Method)
    at java.security.AccessControlContext$1.doIntersectionPrivilege(Unknown Source)
    at java.awt.EventQueue.dispatchEvent(Unknown Source)
    at java.awt.EventDispatchThread.pumpOneEventForFilters(Unknown Source)
    at java.awt.EventDispatchThread.pumpEventsForFilter(Unknown Source)
    at java.awt.EventDispatchThread.pumpEventsForHierarchy(Unknown Source)
    at java.awt.EventDispatchThread.pumpEvents(Unknown Source)
    at java.awt.EventDispatchThread.pumpEvents(Unknown Source)
    at java.awt.EventDispatchThread.run(Unknown Source)
Run Code Online (Sandbox Code Playgroud)

据我了解,该show方法抱怨btn没有显示.如何btnactionPerformed调用方法时不显示?

这个堆栈跟踪中最奇怪的事情是该actionPerformed方法似乎FocusEvent是在处理a时触发的(focusLost实际上是a).

问题是:你能解释一下这种堆栈跟踪是如何发生的吗?

结语

感谢trashgod的建议,我发现了问题.

在Windows上,当按下按钮时按钮消失,然后触发其ActionListener,就像单击按钮一样.可以在Windows上观察到此行为,但在Linux上则不会.

我在Oracle/Sun bug数据库中提交了一个错误.链接在这里 :

http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=7115421

(此链接将在Java团队审核后的几天内生效).

谢谢你的帮助.来自trashgod和Thomas的答案帮助很大.

tra*_*god 6

一个可能的来源是竞争条件,允许事件在收件人可见之前触发.验证是否事件派发线程上构造和操作Swing GUI对象.文章调试摇摆,最后总结中引用如何生成的RepaintManager例外提到了几种方法来自动搜索.