23

When the program starts, a new JFrame is created. Once the user clicks the start button a thread is created and started. Part of this threads execution is to validate the data on the form and then execute with that data. Once the data has been validated the thread calls dispose() on the original frame and then creates a new JFrame that acts as a control panel.

There is also an automatic mode of the program that doesn't display any GUI at all, this mode reads data from a configuration file and then starts the execution thread and runs everything but without the control panel.

I want the program to end once the thread completes, but in GUI mode, only if the user has closed the control panel as well. Is it possible to make the thread wait for the frame to close. I assuming that the frame is run from it's own Thread? or is that not the case.

Thanks.

A Jackson
  • 2,776
  • 7
  • 34
  • 45

3 Answers3

32

The answer you chose is a little awkward. Using Thread.sleep(1000) will check for window state every second. It is not a performance issue, but just bad coding style. And you may have a one second response time.

This code is a little bit better.

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();
}
Markus W Mahlberg
  • 19,711
  • 6
  • 65
  • 89
Denis Tulskiy
  • 19,012
  • 6
  • 50
  • 68
4

You can make reference from your thread to the JFrame. Then set the default close operation of JFrame to HIDE_ON_CLOSE. If the JFrame is closed, you can stop the thread.

Example code:

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();
    }
} 
nanda
  • 24,458
  • 13
  • 71
  • 90
  • This has the advantage of being a little less tightly bound than the other answer. The fact that the frame and the thread both have to know about each other in the other answer is somewhat problematic for me. Also the sleep could be dropped quite a bit and not effect performance. I often go with a sleep(100) which is almost completely unnoticeable. – Bill K Nov 14 '19 at 17:38
3

All Swing components, including JFrame, are managed by a single thread, called the Event Dispatch Thread, or EDT. (It's possible to call methods on Swing objects from other threads, but this is usually unsafe, except in a few cases not relevant here.)

You'll probably accomplish what you want here by putting the data validation and execution code in its own object which is otherwise completely unaware of the outside world. Then, call it from one of two other objects: one that manages a GUI, and another that runs in "automatic mode".

Paul Brinkley
  • 6,283
  • 3
  • 24
  • 33