问题
Edit: In case the multiple tags are confusing, I'm working in Jython.
Here's my SSCCE:
from javax.swing import JFrame
window = JFrame('Test',
defaultCloseOperation = JFrame.EXIT_ON_CLOSE,
size = (800, 600))
window.visible = True
The window opens, sits there for a few seconds, and then closes. So far the only solution I've found is to add while True: pass
to the end, which would seem to indicate that the problem is that window
is going out of scope, so it gets cleaned up and has to close. This may in fact be another symptom of the same problem I have encountered previously.
However, I don't think wasting cycles in an infinite loop is the best solution. I guess I could make it less of an issue by sleeping for a few seconds on each loop, but I would still like to solve this properly.
Doing things the 'right way', creating the window on the EDT, gives exactly the same behaviour:
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)
In previous applications this hasn't been a problem, because I've needed an infinite loop for other tasks anyway (monitoring sockets etc). However, my current application is driven purely by user input, so I don't need/want anything after I invokeLater()
.
Update: Based on kingo's answer, I tried instantiating one of these:
class JFrameTest(JFrame):
def addNotify(self):
print 'In addNotify()'
JFrame.addNotify(self)
def removeNotify(self):
print "In removeNotify()"
JFrame.removeNotify(self)
"In addNotify()" is printed, but not "In removeNotify()", and the window behaves the same. Why would removeNotify()
not be being called?
Also, I have tried doing window.setVisible(True)
rather than window.visible = True
, and that has no effect either.
回答1:
I suggest the following strategy to learn more about the problem:
sun.awt.AWTAutoShutdown
is the class that prevents shutdown of the JVM if a native window peer is registered with the toolkit. Any component is registered when addNotify()
is called on it. For a frame, this is done when you call setVisible(true)
.
The only way a peer can get unregistered is if somebody calls dispose()
on the peer. The only place dispose()
is called on a peer in the JRE is from Component#removeNotify()
.
You could override that method in your frame class and print a stack trace to see why that happens.
来源:https://stackoverflow.com/questions/7438848/why-does-my-swing-window-keep-closing-itself-after-a-few-seconds