为什么我的Swing窗口几秒后就自动关闭?
补充说明:为了避免多个标签让人困惑,我是在使用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 个回答
我建议你可以用以下方法来更好地理解这个问题:
sun.awt.AWTAutoShutdown
是一个类,它的作用是防止Java虚拟机(JVM)关闭,前提是有一个本地窗口的“伙伴”被注册到工具包中。任何组件在调用 addNotify()
时就会被注册。对于一个窗口来说,当你调用 setVisible(true)
时,就会完成这个注册。
要想让一个“伙伴”被注销,唯一的方法就是有人对这个“伙伴”调用 dispose()
。在Java运行环境(JRE)中,唯一会对“伙伴”调用 dispose()
的地方是 Component#removeNotify()
。
你可以在你的窗口类中重写这个方法,并打印出一个堆栈跟踪,以便查看为什么会发生这种情况。