【发布时间】:2011-10-28 10:52:07
【问题描述】:
是否可以以标准方式执行此操作?
这是场景。
开始在 EDT 中做一些昂贵的事情(EDT 被阻塞,直到昂贵的操作结束)。
当 EDT 被阻止时,用户继续单击/拖动鼠标按钮。所有鼠标动作都记录在某处。
当 EDT 空闲时(用昂贵的东西完成),它开始处理鼠标事件。
我想要在第 3 步中丢弃堆积的鼠标事件。在 EDT 空闲后,任何新的鼠标事件都应该以通常的方式处理。
关于如何实现这一点的任何想法。
PS:我无法阻止 EDT 被阻塞(我无法控制程序中某些模块的行为)。
编辑: 如果我可以安全地调用“SunToolkit.flushPendingEvents()”,那么我总是可以在 EDT 中开始昂贵的操作之前放置一个玻璃窗格。在 EDT 线程上的昂贵操作结束后,刷新所有事件 - 它们将进入一个不会做任何事情的玻璃窗格。然后让 EDT 正常工作。
编辑2: 我添加了一个 SSCCE 来演示这个问题。
公共类 BusyCursorTest2 扩展 javax.swing.JFrame { 公共 BusyCursorTest2() { javax.swing.JButton wait = new javax.swing.JButton("等待 3 秒"); getContentPane().setLayout(new java.awt.GridLayout(2, 1, 0, 0)); getContentPane().add(等待); getContentPane().add(new javax.swing.JToggleButton("点击我")); setTitle("忙碌光标"); 设置大小(300、200); setDefaultCloseOperation(javax.swing.JFrame.DISPOSE_ON_CLOSE); 设置可见(真); wait.addActionListener(new java.awt.event.ActionListener() { 公共无效actionPerformed(java.awt.event.ActionEvent事件){ final java.util.Timer timer = switchToBusyCursor(BusyCursorTest2.this); 尝试 { //在 EDT 中做一些昂贵的事情 尝试 { 线程.sleep(3000); } 捕捉(InterruptedException e){ //没做什么 } } 最后 { switchToNormalCursor(BusyCursorTest2.this, timer); } } }); } 公共静态 java.util.Timer switchToBusyCursor(final javax.swing.JFrame frame) { 开始事件陷阱(帧); java.util.TimerTask timerTask = new java.util.TimerTask() { 公共无效运行(){ startWaitCursor(帧); } }; final java.util.Timer timer = new java.util.Timer(); timer.schedule(timerTask, DELAY_MS); 返回计时器; } public static void switchToNormalCursor(final javax.swing.JFrame frame, final java.util.Timer timer) { 计时器.取消(); 停止等待光标(帧); 停止事件陷阱(帧); } 私有静态无效 startWaitCursor(javax.swing.JFrame 框架) { frame.getGlassPane().setCursor(java.awt.Cursor.getPredefinedCursor(java.awt.Cursor.WAIT_CURSOR)); frame.getGlassPane().addMouseListener(mouseAdapter); frame.getGlassPane().setVisible(true); } 私有静态无效 stopWaitCursor(javax.swing.JFrame 框架) { frame.getGlassPane().setCursor(java.awt.Cursor.getPredefinedCursor(java.awt.Cursor.DEFAULT_CURSOR)); frame.getGlassPane().removeMouseListener(mouseAdapter); frame.getGlassPane().setVisible(false); } 私有静态无效 startEventTrap(javax.swing.JFrame 框架){ frame.getGlassPane().addMouseListener(mouseAdapter); frame.getGlassPane().setVisible(true); } 私有静态无效stopEventTrap(javax.swing.JFrame框架){ frame.getGlassPane().removeMouseListener(mouseAdapter); frame.getGlassPane().setVisible(false); } 私有静态最终 java.awt.event.MouseAdapter mouseAdapter = new java.awt.event.MouseAdapter() { }; 公共静态无效主要(字符串[]参数){ javax.swing.SwingUtilities.invokeLater(new Runnable() { 公共无效运行(){ 新的 BusyCursorTest2(); } }); } 私有静态最终 int DELAY_MS = 250; }运行 SSCCE
单击“等待 3 秒”按钮。它模拟了昂贵的操作。鼠标光标将变为忙碌状态。
当光标处于忙碌状态时,单击切换按钮“单击我”。如果在三秒后,切换按钮改变了状态,那么鼠标事件被切换按钮接收到并且没有被捕获。
我希望当光标看起来很忙时,丢弃生成的鼠标(和其他)事件。
谢谢。
【问题讨论】:
-
不,大多数swing组件(所有不同的面板及其内容等)都是由不同的开发人员完成的,并且可能随时更改。我无法对这些摆动组件做出任何假设。我只能在 rootpane 上制作可见的 glasspane 以防止他们获取事件。
-
您有两种解决方案。 1)将昂贵的操作放在工作线程上。 2) 使用玻璃板阻止其他事件。 Swing 并非旨在保护应用免受开发人员的侵害。
-
不是从 EventQueue 更改或拆分一致性的好方法,但通过在此论坛中进行最深入的搜索
EventQueue theQueue = getToolkit().getSystemEventQueue();不要明白,如果您手动将任何事件发送到 EDT,所有等待线程都会迷失了,永远停留在现在的形式,干脆不要那样做, -
1) 不要 2) 不要 3) 不要 - 或者换句话说:与其花心思去做一些令人难以置信的反摇摆的事情,不如把所有的精力都放在说服谁负责,这是一个 no-no-never-ever,它将在未来的任何时候产生不可预测的维护痛苦
标签: java swing event-dispatch-thread eventqueue