Java图形程序未按预期关闭

时间:2015-12-07 14:16:28

标签: java swing

我正在尝试在内置的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!");
    }
}

3 个答案:

答案 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;解决了这个问题。

全部谢谢!