Как заставить поток ждать закрытия JFrame в Java? - PullRequest
17 голосов
/ 27 августа 2009

Когда программа запускается, создается новый JFrame. Когда пользователь нажимает кнопку «Пуск», создается и запускается поток. Частью выполнения этих потоков является проверка данных в форме, а затем выполнение с этими данными. После проверки данных поток вызывает dispose () для исходного кадра, а затем создает новый JFrame, который действует как панель управления.

Существует также автоматический режим программы, который вообще не отображает GUI, этот режим считывает данные из файла конфигурации, а затем запускает поток выполнения и запускает все, но без панели управления.

Я хочу, чтобы программа заканчивалась после завершения потока, но в режиме графического интерфейса пользователя, только если пользователь также закрыл панель управления. Можно ли заставить поток ждать закрытия кадра. Я предполагаю, что кадр запускается из своего собственного потока? или это не тот случай.

Спасибо.

Ответы [ 3 ]

24 голосов
/ 27 августа 2009

Ответ, который вы выбрали, немного неловкий. Использование Thread.sleep (1000) будет проверять состояние окна каждую секунду. Это не проблема производительности, а просто плохой стиль кодирования. И у вас может быть время отклика в одну секунду.

Этот код немного лучше.

private static Object lock = new Object();
private static JFrame frame = new JFrame();
/**
 * @param args
 */
public static void main(String[] args) {

    frame.setSize(300, 300);
    frame.setDefaultCloseOperation(JFrame.HIDE_ON_CLOSE);
    frame.setVisible(true);

    Thread t = new Thread() {
        public void run() {
            synchronized(lock) {
                while (frame.isVisible())
                    try {
                        lock.wait();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                System.out.println("Working now");
            }
        }
    };
    t.start();

    frame.addWindowListener(new WindowAdapter() {

        @Override
        public void windowClosing(WindowEvent arg0) {
            synchronized (lock) {
                frame.setVisible(false);
                lock.notify();
            }
        }

    });

    t.join();
}
2 голосов
/ 27 августа 2009

Все компоненты Swing, включая JFrame, управляются одним потоком, называемым потоком диспетчеризации событий, или EDT. (Можно вызывать методы на объектах Swing из других потоков, но это обычно небезопасно, за исключением некоторых случаев, не относящихся к делу.)

Вы, вероятно, достигнете того, что вам нужно, поместив код проверки и выполнения данных в свой собственный объект, который иначе совершенно не знает о внешнем мире. Затем вызовите его из одного из двух других объектов: один управляет графическим интерфейсом, а другой работает в «автоматическом режиме».

1 голос
/ 27 августа 2009

Вы можете сделать ссылку из вашей темы на JFrame. Затем установите для операции закрытия JFrame по умолчанию значение HIDE_ON_CLOSE . Если JFrame закрыт, вы можете остановить поток.

Пример кода:

import java.awt.Dimension;

import javax.swing.JFrame;

public class FrameExample extends JFrame {

    public FrameExample() {
        setSize(new Dimension(100, 100));
        setDefaultCloseOperation(HIDE_ON_CLOSE);
        setVisible(true);

    }

    private static class T implements Runnable {

        private FrameExample e;

    public T(FrameExample e) {
        this.e = e;
    }

    @Override
    public void run() {
        while (true) {
            if (e.isVisible()) {
                // do the validation
                System.out.println("validation");
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e1) {
                    break;
                }
            }
        }
    }

}

public static void main(String[] args) {
    FrameExample frameExample = new FrameExample();

    new Thread(new T(frameExample)).start();
    }
} 
...