Java Swing Dialog, how to call wait method when capturing WindowClosing event -
i have jruby script opens java dialog report on progress of script.
i capturing windowclosing event, , want dialog wait until cleanup in jruby script has occurred, , dispose. instead, dialog hangs when user presses top right red x button.
how correctly call wait method wait on flag change? using lock object correctly?
a jruby script calls dialog.
if user presses top right red x, dialog captures windowclosing event , sets 'cancelled' flag. script keeps eye on flag, starts shutting down long running tasks , not . when done, updates flag on dialog cleanup has occurred. meanwhile, dialog looping, waiting on flag change. calls dispose().
i've tried using sleep. reason, upsets between jruby , dialog, cleanup occurs okay, dialog not dispose.
using wait, synchronize(this) generates illegalmonitorexception, script cleans , dialog dispose correctly apart exception.
have looked @ bunch of other posts on how synchorize wait method, understand this.
thanks assistance.
dialog class follows:
import javax.swing.*; import java.awt.*; public class mydialog extends jdialog { private boolean usercancelled; private boolean scriptcleanedup; //private static object lock = new object(); public mydialog(lock) { usercancelled = false; scriptcleanedup = false; setdefaultcloseoperation(2); //[..] add various controls dialog addwindowlistener(new windowadapter() { public void windowclosing(windowevent we) { // jruby script keeps eye on flag see if user has cancelled dialog usercancelled = true; /* once cancelled, wait script flag has performed cleanup */ /* here problem area, need synchronize use wait method? */ while (!scriptcleanedup) { try { synchronized (lock) { lock.wait(1000000000); } // thread.sleep(1000); } catch (interruptedexception e) { e.printstacktrace(); } } dispose(); } }); super.paint(super.getgraphics()); } public boolean user_cancelled() { return usercancelled; } public void setscriptcleaneduptotrue() { this.scriptcleanedup = true; } public static void forblock(mydialogblockinterface block) { mydialog dialog = new mydialog(new object()); dialog.setvisible(true); block.dowork(dialog); dialog.dispose(); } }
and if helps, how jruby script calls dialog
mydialog.forblock |dialog| #do long running jruby task here end
you've got lot of problems code including:
- you're making long-running calls on swing event thread, tie critical thread , guaranteed freeze gui.
- your calling
paint(...)
directly, should never done.
i'll bet of problem called making sure dialog modal jdialog, if make long-running calls in background thread such swingworker, , rather trying wait lock released, use call-back mechanism notify dialog shut down.
for example:
import java.awt.dialog.modalitytype; import java.awt.dimension; import java.awt.window; import java.awt.event.actionevent; import java.awt.event.windowadapter; import java.awt.event.windowevent; import java.beans.propertychangeevent; import java.beans.propertychangelistener; import java.util.concurrent.executionexception; import java.util.concurrent.atomic.atomicboolean; import javax.swing.*; /** * http://stackoverflow.com/a/29933423/522444 * @author pete * */ @suppresswarnings("serial") public class testmydialog2 extends jpanel { private static final int pref_w = 400; private static final int pref_h = pref_w; public testmydialog2() { add(new jbutton(new mydialogaction("please press button!", this))); } @override public dimension getpreferredsize() { if (ispreferredsizeset()) { return super.getpreferredsize(); } // let's make reasonably big return new dimension(pref_w, pref_h); } private static void createandshowgui() { testmydialog2 mainpanel = new testmydialog2(); jframe frame = new jframe("testmydialog2"); frame.setdefaultcloseoperation(jframe.dispose_on_close); frame.getcontentpane().add(mainpanel); frame.pack(); frame.setlocationbyplatform(true); frame.setvisible(true); } public static void main(string[] args) { swingutilities.invokelater(new runnable() { public void run() { createandshowgui(); } }); } } @suppresswarnings("serial") class mydialogaction extends abstractaction { private jdialog dialog; private myworker myworker; private testmydialog2 testmydialog2; public mydialogaction(string name, testmydialog2 testmydialog2) { super(name); int mnemonic = (int) name.charat(0); putvalue(mnemonic_key, mnemonic); this.testmydialog2 = testmydialog2; } public void dialogisclosing(windowevent e) { if (myworker != null && !myworker.isdone()) { myworker.setkeeprunning(false); } else { if (dialog != null && dialog.isvisible()) { dialog.dispose(); } } } @override public void actionperformed(actionevent e) { window maingui = swingutilities.getwindowancestor(testmydialog2); dialog = new jdialog(maingui, "my dialog", modalitytype.application_modal); dialog.setdefaultcloseoperation(jdialog.do_nothing_on_close); dialog.add(box.createrigidarea(new dimension(200, 100))); dialog.addwindowlistener(new dialogwindowlistener(this)); dialog.pack(); myworker = new myworker(); myworker.addpropertychangelistener(new myworkerlistener(dialog)); myworker.execute(); dialog.setlocationrelativeto(maingui); dialog.setvisible(true); } } class myworker extends swingworker<void, void> { private volatile atomicboolean keeprunning = new atomicboolean(true); @override protected void doinbackground() throws exception { // emulate long-running code while (keeprunning.get()) { thread.sleep(200); system.out.println("long running background code running"); } system.out.println("doing shut-down process. close in 10 seconds"); (int = 0; < 10; i++) { system.out.println("countdown: " + (10 - i)); thread.sleep(1000); // emulate long running shut-down process } return null; } public void setkeeprunning(boolean newvalue) { this.keeprunning.getandset(newvalue); } } class myworkerlistener implements propertychangelistener { private jdialog dialog; public myworkerlistener(jdialog dialog) { this.dialog = dialog; } @override public void propertychange(propertychangeevent evt) { if (evt.getnewvalue() == swingworker.statevalue.done) { dialog.dispose(); try { ((myworker) evt.getsource()).get(); } catch (interruptedexception e) { e.printstacktrace(); } catch (executionexception e) { e.printstacktrace(); } } } } class dialogwindowlistener extends windowadapter { private mydialogaction mydialogaction; public dialogwindowlistener(mydialogaction mydialogaction) { this.mydialogaction = mydialogaction; } @override public void windowclosing(windowevent e) { mydialogaction.dialogisclosing(e); } }
Comments
Post a Comment