我正在尝试在内置的Java图形系统之上创建一种简化的图形库。我想在教学中使用它,这样学生就可以创建图形程序而无需创建自己的类,或者特别需要使用继承。
无论如何,正如我所拥有的那样,窗户并没有像我期望的那样关闭,我无法弄清楚原因。奇怪的是,如果我在主程序循环中有一个println, 就可以了。这是怎么回事?这是一个最小的例子:
package test;
import javax.swing.JFrame;
import java.awt.event.WindowListener;
import java.awt.event.WindowEvent;
import java.util.Queue;
import java.util.LinkedList;
/** enumeration of the different types of events which a window can produce */
enum EventType {
Closed,
KeyPressed,
KeyReleased,
MousePressed,
MouseReleased,
MouseMoved
}
/** a class which represents an event which a window can produce */
class Event {
private EventType t;
/** create a new event of a given type */
public Event(EventType type) {
t = type;
}
/** check which type of event it is */
public EventType getType( ) {
return t;
}
}
/** a graphics window */
class Window implements WindowListener {
private JFrame frame;
private boolean open;
private Queue<Event> events;
/** create the window */
public Window(String title, int width, int height, boolean resizable) {
frame = new JFrame(title);
frame.setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE);
frame.setSize(width, height);
frame.setResizable(resizable);
frame.setVisible(true);
frame.addWindowListener(this);
events = new LinkedList<>( );
open = true;
}
/** checks whether the window is still open or not */
public boolean isOpen( ) {
return open;
}
/** closes the window */
public void close( ) {
open = false;
frame.dispose( );
}
/** returns the next event, or null if there is none */
public Event pollEvent( ) {
return events.poll( );
}
/* functions which implement window listening */
public void windowOpened(WindowEvent e) { }
public void windowIconified(WindowEvent e) { }
public void windowDeiconified(WindowEvent e) { }
public void windowActivated(WindowEvent e) { }
public void windowDeactivated(WindowEvent e) { }
public void windowClosed(WindowEvent e) { }
public void windowClosing(WindowEvent e) {
System.out.println("Adding close event");
events.add(new Event(EventType.Closed));
}
}
public class Test {
public static void main(String args[]) {
// create the window
Window window = new Window("Hello world!", 800, 600, false);
// while the window is open
while (window.isOpen( )) {
// check for events
Event event = window.pollEvent( );
if (event != null) {
switch (event.getType( )) {
// handle the window close event
case Closed:
System.out.println("Calling close");
window.close( );
break;
}
}
// when this line is un-commented, it works as expected???
//System.out.print('.');
}
System.out.println("All done!");
}
}
答案 0 :(得分:2)
确保您从EDT致电dispose()
。这应该适合你:
switch (event.getType()) {
// handle the window close event
case Closed:
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
System.out.println("Calling close");
window.close();
}
});
break;
}
答案 1 :(得分:1)
尝试更改
frame.setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE);
到
frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
答案 2 :(得分:1)
好的,我明白了。问题是Java事件线程和我的主线程之间缺乏同步。我的主要线程是不断调用从事件队列中提取事件。
然后,Java事件线程会在某个时刻将close事件添加到队列中。这是不同步的,所以事件不知何故丢失了。我估计它被称为&#34;期间&#34;检查队列并没有提交。
添加&#34; synchronized&#34;关键字to&#34; windowClosing&#34;将事件排队,以及&#34; pollEvent&#34;解决了这个问题。
全部谢谢!