PDA

View Full Version : [SOLVED] [Java] hide/dispose of window



SpinningAround
January 21st, 2010, 01:36 PM
I'm have a little program that create a window from an other java class. In this window will the user make a few decisions then click on [FINISH] (or [EXIT]), when [FINISH] is clicked should the JFrame close down and the main program continue to evaluate the decisions. Problem is that I'm not quite sure in how to dispose of the window and get it to return to the main program, as it's now will the main program create the window and continue. I guess it's possible to make a while loop that check for a change in the window program, but it feels like an ugly solution.

I tried to get it working the last ours but can't figure out how Thread.wait() and Thread.sleep() work. This don't work.



public static Thread mainApp= Thread.currentThread();
public static void main(String args[]) throws InterruptedException{
MonitorGraphic window = new MonitorGraphic();
mainApp.wait();
window.dispose();




@MonitorGraphic
...
VpnMonitor.mainApp.notify();
...



Give this


Exception in thread "main" java.lang.IllegalMonitorStateException
at java.lang.Object.wait(Native Method)
at java.lang.Object.wait(Object.java:485)
at Monitor.main(Monitor.java:110)
<==? DEBUG | RETURN TO MAIN ?==>
Exception in thread "AWT-EventQueue-0" java.lang.IllegalMonitorStateException
at java.lang.Object.notify(Native Method)
at MonitorGraphic.actionPerformed(MonitorGraphic.java :167)
at javax.swing.AbstractButton.fireActionPerformed(Abs tractButton.java:1995)
at javax.swing.AbstractButton$Handler.actionPerformed (AbstractButton.java:2318)
at javax.swing.DefaultButtonModel.fireActionPerformed (DefaultButtonModel.java:387)
at javax.swing.DefaultButtonModel.setPressed(DefaultB uttonModel.java:242)
at javax.swing.plaf.basic.BasicButtonListener.mouseRe leased(BasicButtonListener.java:236)
at java.awt.Component.processMouseEvent(Component.jav a:6263)
at javax.swing.JComponent.processMouseEvent(JComponen t.java:3267)
at java.awt.Component.processEvent(Component.java:602 8)
at java.awt.Container.processEvent(Container.java:204 1)
at java.awt.Component.dispatchEventImpl(Component.jav a:4630)
at java.awt.Container.dispatchEventImpl(Container.jav a:2099)
at java.awt.Component.dispatchEvent(Component.java:44 60)
at java.awt.LightweightDispatcher.retargetMouseEvent( Container.java:4574)
at java.awt.LightweightDispatcher.processMouseEvent(C ontainer.java:4238)
at java.awt.LightweightDispatcher.dispatchEvent(Conta iner.java:4168)
at java.awt.Container.dispatchEventImpl(Container.jav a:2085)
at java.awt.Window.dispatchEventImpl(Window.java:2475 )
at java.awt.Component.dispatchEvent(Component.java:44 60)
at java.awt.EventQueue.dispatchEvent(EventQueue.java: 599)
at java.awt.EventDispatchThread.pumpOneEventForFilter s(EventDispatchThread.java:269)
at java.awt.EventDispatchThread.pumpEventsForFilter(E ventDispatchThread.java:184)
at java.awt.EventDispatchThread.pumpEventsForHierarch y(EventDispatchThread.java:174)
at java.awt.EventDispatchThread.pumpEvents(EventDispa tchThread.java:169)
at java.awt.EventDispatchThread.pumpEvents(EventDispa tchThread.java:161)
at java.awt.EventDispatchThread.run(EventDispatchThre ad.java:122)

Axos
January 21st, 2010, 11:41 PM
There are other potential problems with what you are trying to do but the solution to the IllegalMonitorStateException is for both the waiter and notifier to synchronize on the object before calling the wait or notify (or notifyAll) methods. Note that there is nothing special about the object. It is not necessary to use an instance of Thread. In the example below, I just create an instance of Object.

Note also that it is not safe to call any Swing-related methods (directly or indirectly) on anything besides the Swing event dispatching thread. That includes creating Windows. In the example below, the method MainFrame.main takes care of calling java.awt.EventQueue.invokeLater to create an instance of the frame on the dispatch thread. (This is a convenience method generated by the NetBeans IDE when you add a JFrame to your project, though I've modified it to accept the synchronization object as a parameter.)



public class Main {

private static final Object foo = new Object();

/**
* @param args the command line arguments
*/
public static void main(String[] args) {
synchronized(foo) {
MainFrame.main(foo);
try {
foo.wait();
System.out.println("wait returned!");
} catch (InterruptedException ex) {
Logger.getLogger(Main.class.getName()).log(Level.S EVERE, null, ex);
}
}
}

}




public class MainFrame extends javax.swing.JFrame {

private final Object waiter;

/** Creates new form MainFrame */
public MainFrame(Object waiter) {
this.waiter = waiter;
//...
}

public static void main(final Object waiter) {
java.awt.EventQueue.invokeLater(new Runnable() {
public void run() {
new MainFrame(waiter).setVisible(true);
}
});
}

private void jButton1ActionPerformed(java.awt.event.ActionEvent evt) {
synchronized(waiter) {
waiter.notifyAll();
}

// code for hiding or closing frame omitted...not relevant to example
}

}

Axos
January 22nd, 2010, 12:05 AM
Rather than using the solution I posted above, you might want to consider reorganizing your program so that the GUI calls the application code (the "meat" of the program) rather than the application code calling the GUI. When designing a non-trivial program, it's a good idea to keep the application code as separate as possible from the GUI. Organize the application code like a library so that it can be called by any kind of program, GUI or non-GUI.

But if you want to keep your current design, be aware that every possible way the window can be dismissed must take care of calling the notifyAll method to notify the waiting thread.

SpinningAround
January 22nd, 2010, 11:55 AM
Thanks :D I'm will go for your last solution, will try to implement the thread solution when I better understand it.