为什么我的Swing窗口几秒后就自动关闭?

3 投票
1 回答
1472 浏览
提问于 2025-04-17 02:24

补充说明:为了避免多个标签让人困惑,我是在使用Jython。

这是我的简化示例

from javax.swing import JFrame

window = JFrame('Test', 
                defaultCloseOperation = JFrame.EXIT_ON_CLOSE,
                size = (800, 600))
window.visible = True

窗口打开后,停留几秒钟,然后就关掉了。目前我找到的唯一解决办法是在最后加上while True: pass,这似乎表明问题在于window超出了作用域,所以它被清理掉了,必须关闭。实际上,这可能是我之前遇到的同样问题的另一个表现

不过,我觉得在无限循环中浪费资源并不是最佳解决方案。我可以通过在每次循环中暂停几秒来减轻这个问题,但我还是希望能正确地解决这个问题。

按照“正确的方式”,在EDT上创建窗口,结果表现和之前一样:

from javax.swing import JFrame, SwingUtilities
from java.lang import Runnable

class Foo(Runnable):
    def run(self):
        window = JFrame('Test', 
                        defaultCloseOperation = JFrame.EXIT_ON_CLOSE,
                        size = (800, 600))
        window.visible = True

foo = Foo()
SwingUtilities.invokeLater(foo)

在之前的应用中,这并不是问题,因为我本来就需要一个无限循环来处理其他任务(比如监控套接字等)。但是我现在的应用完全是由用户输入驱动的,所以在我invokeLater()之后不需要/不想要任何东西。

更新:根据kingo的回答,我尝试实例化其中一个:

class JFrameTest(JFrame):
    def addNotify(self):
        print 'In addNotify()'
        JFrame.addNotify(self)

    def removeNotify(self):
        print "In removeNotify()"
        JFrame.removeNotify(self)

打印了“In addNotify()”,但没有打印“In removeNotify()”,而且窗口的表现还是一样。为什么removeNotify()没有被调用呢?

另外,我尝试使用window.setVisible(True)而不是window.visible = True,但也没有效果。

1 个回答

0

我建议你可以用以下方法来更好地理解这个问题:

sun.awt.AWTAutoShutdown 是一个类,它的作用是防止Java虚拟机(JVM)关闭,前提是有一个本地窗口的“伙伴”被注册到工具包中。任何组件在调用 addNotify() 时就会被注册。对于一个窗口来说,当你调用 setVisible(true) 时,就会完成这个注册。

要想让一个“伙伴”被注销,唯一的方法就是有人对这个“伙伴”调用 dispose()。在Java运行环境(JRE)中,唯一会对“伙伴”调用 dispose() 的地方是 Component#removeNotify()

你可以在你的窗口类中重写这个方法,并打印出一个堆栈跟踪,以便查看为什么会发生这种情况。

撰写回答