awt - How to display Java dialog using alternate event queue? -
i have code detects if java awt event queue frozen (busy processing event or waiting lock) excessive amount of time, due buggy foreign code fails use swingworker
or similar, , want offer recover. killing event dispatch thread thread.stop
works, hazardous (and eq might blocked because computer temporarily overloaded), prefer prompt user confirmation. displaying dialog requires waiting eq unblocked, not possible.
is there way, reasonably portable java program, display dialog (or kind of ui element can respond input events) without involving normal event queue?
i tried running systemtray.add(trayicon)
, manage display tray item when called thread... icon not painted, , actionevent
s not delivered, not helpful.
it seems possible display new jframe
, paint label on using paintimmediately
, there still no apparent way receive mouse events.
following tom hawtin's hint, tried create new appcontext
. on jdk 6u18, dialog shown in new context seems paint correctly not receive mouse events until main event queue unblocked, defeating purpose:
import java.awt.eventqueue; import java.awt.event.actionevent; import java.awt.event.actionlistener; import java.util.map; import java.util.concurrent.executors; import java.util.concurrent.scheduledexecutorservice; import java.util.concurrent.timeunit; import javax.swing.jbutton; import javax.swing.jdialog; import javax.swing.jframe; import javax.swing.windowconstants; import sun.awt.appcontext; import sun.awt.suntoolkit; public class main { public static void main(string[] args) { eventqueue.invokelater(new runnable() { public @override void run() { new mainwindow().setvisible(true); system.err.println("main context: " + appcontext.getappcontext()); } }); new trackeq(1000*3); } private static class mainwindow extends jframe { mainwindow() { setdefaultcloseoperation(windowconstants.exit_on_close); jbutton pause = new jbutton("pause"); pause.addactionlistener(new actionlistener() { public @override void actionperformed(actionevent e) { try { thread.sleep(15000); } catch (interruptedexception x) { x.printstacktrace(); } } }); getcontentpane().add(pause); pack(); setlocation(100, 100); } } private static class trackeq implements runnable { private final scheduledexecutorservice svc; private final int timeout; private boolean stuck = false; private boolean wait = false; private thread eq; trackeq(int timeout) { this.timeout = timeout; svc = executors.newsinglethreadscheduledexecutor(); svc.schedule(this, 0, timeunit.milliseconds); } public @override synchronized void run() { if (eventqueue.isdispatchthread()) { stuck = false; eq = thread.currentthread(); } else { if (stuck && !wait) { system.err.println("ui stuck!"); wait = true; map<thread,stacktraceelement[]> stacktraces = thread.getallstacktraces(); stacktraceelement[] stack = stacktraces.get(eq); if (stack != null) { (stacktraceelement el : stack) { system.err.println("stuck @ " + el); } threadgroup grp = new threadgroup("showing dialog"); grp.setdaemon(true); new thread(grp, new runnable() { public @override void run() { system.err.println("created new app context in " + thread.currentthread().getthreadgroup()); suntoolkit.createnewappcontext(); eventqueue.invokelater(new runnable() { public @override void run() { system.err.println("main eq=" + eq + " whereas eq=" + thread.currentthread()); system.err.println("will show dialog in " + appcontext.getappcontext()); final jdialog dlg = new jdialog(); dlg.setdefaultcloseoperation(windowconstants.dispose_on_close); jbutton fix = new jbutton("fix!"); fix.addactionlistener(new actionlistener() { @suppresswarnings("deprecation") public @override void actionperformed(actionevent e) { system.err.println("agreed fix"); eq.stop(); wait = false; dlg.setvisible(false); } }); dlg.getcontentpane().add(fix); dlg.pack(); dlg.setlocation(200, 100); dlg.setvisible(true); system.err.println("showed dialog"); } }); } }, "showing dialog").start(); } else { system.err.println("no stack trace " + eq + "; listed threads: " + stacktraces.keyset()); } } else { stuck = true; } eventqueue.invokelater(this); svc.schedule(this, timeout, timeunit.milliseconds); } } } private main() {} }
the awt apis written if there event queue. talking mutable statics , hence bad design , evil hacks.
the sun plugin , webstart use undocumented api hack in context. check out appcontext
class. context looked first threadgroup
and, if inconclusive, examining classloader
s on stack.
obvious comments: of course run separate process. application make sure don't block critical resources including edt.
Comments
Post a Comment