java如何在对话框响应事件_如何使用备用事件队列显示Java对话框?

我有一些代码可以检测Java AWT事件队列是否被冻结(忙于处理某个事件或等待锁定)一段时间过长,因为有些错误的外国代码无法使用SwingWorker或类似的东西,我想提供给恢复.只是使用Thread.stop杀死事件派发线程,但它可能是危险的(并且EQ可能因为计算机暂时过载而被阻止),所以我宁愿提示用户进行确认.但是,显示一个对话框需要等待EQ被解除阻塞,这正是不可能的.

从一个合理的可移植Java程序,有没有办法显示一个对话框(或任何一种可以响应输入事件的UI元素),而不涉及正常的事件队列?

我已经尝试过运行SystemTray.add(TrayIcon),它确实设法在从另一个线程调用时显示一个托盘项…但是图标没有绘制,并且ActionEvents没有交付,所以这没有帮助.

它似乎也可以显示一个新的JFrame,甚至可以使用paintImmediately在其上绘制标签,但仍然没有明显的方法来接收鼠标事件.

在Tom Hawtin的提示之后,我尝试创建一个新的AppContext.在JDK 6u18上,新上下文中显示的对话框似乎正确绘制,但在主事件队列被解除阻塞之前不会接收鼠标事件,从而破坏了目的:

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 is stuck!");

wait = true;

Map stackTraces = Thread.getAllStackTraces();

StackTraceElement[] stack = stackTraces.get(eq);

if (stack != null) {

for (StackTraceElement el : stack) {

System.err.println("stuck at " + 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 my 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 to 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 for " + eq + "; listed threads: " + stackTraces.keySet());

}

} else {

stuck = true;

}

EventQueue.invokeLater(this);

svc.schedule(this, timeout, TimeUnit.MILLISECONDS);

}

}

}

private Main() {}

}

参与评论 您还未登录,请先 登录 后发表或查看评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
©️2022 CSDN 皮肤主题:深蓝海洋 设计师:CSDN官方博客 返回首页

打赏作者

周诗勇

你的鼓励将是我创作的最大动力

¥2 ¥4 ¥6 ¥10 ¥20
输入1-500的整数
余额支付 (余额:-- )
扫码支付
扫码支付:¥2
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、C币套餐、付费专栏及课程。

余额充值