views:

900

answers:

4

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.

+1  A: 

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
Thanks that's just what I needed.
Android
+1  A: 

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
+2  A: 

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();
   }
  }

 });
}
tulskiy
Yeah, I can see why that would be better. Thanks.
Android
I think a t.join() is missing at the end
Mario Ortegón
Yes, thank you.
tulskiy
A: 

That helped a lot! Thank you!

Oyvind Kvalnes
Carlos Heuberger
Ok Carlos. Thanks for the heads up! :)
Oyvind Kvalnes