2011-08-16 45 views
4

是否可以以标准方式执行此操作?java swing清除事件队列

这是场景。

  1. 在美国东部时间开始做一些昂贵的东西(美国东部时间被封锁,直到昂贵的操作结束)。

  2. EDT被阻止时,用户不断点击/拖动鼠标按钮。所有的鼠标操作都被记录在某处。

  3. 当EDT是免费的(使用昂贵的东西)时,它开始处理鼠标事件。

我在第3步想要的是放弃堆积的鼠标事件。 EDT免费后,任何新的鼠标事件都应按照常规方式处理。

关于如何实现这一点的任何想法。 PS:我不可能阻止EDT被阻塞(我不能控制我的程序中某些模块的行为)。

编辑: 如果我可以安全地调用“SunToolkit.flushPendingEvents()”,那么在EDT开始昂贵的操作之前,我总是可以放一块玻璃板。在昂贵的操作结束后,在EDT线上,冲洗所有事件 - 它们将进入不会做任何事情的玻璃窗格。然后让EDT正常工作。

EDIT2: 我已经添加了一个SSCCE来演示这个问题。

 

public class BusyCursorTest2 extends javax.swing.JFrame { 

    public BusyCursorTest2() { 

     javax.swing.JButton wait = new javax.swing.JButton("Wait 3 seconds"); 
     getContentPane().setLayout(new java.awt.GridLayout(2, 1, 0, 0)); 
     getContentPane().add(wait); 
     getContentPane().add(new javax.swing.JToggleButton("Click me")); 
     setTitle("Busy Cursor"); 
     setSize(300, 200); 
     setDefaultCloseOperation(javax.swing.JFrame.DISPOSE_ON_CLOSE); 
     setVisible(true); 

     wait.addActionListener(new java.awt.event.ActionListener() { 

      public void actionPerformed(java.awt.event.ActionEvent event) { 

       final java.util.Timer timer = switchToBusyCursor(BusyCursorTest2.this); 

       try { 
        //do something expensive in EDT 
        try { 
         Thread.sleep(3000); 
        } catch (InterruptedException e) { 
         //do nothing 
        } 
       } finally { 
        switchToNormalCursor(BusyCursorTest2.this, timer); 
       } 
      } 

     }); 
    } 

    public static java.util.Timer switchToBusyCursor(final javax.swing.JFrame frame) { 
     startEventTrap(frame); 
     java.util.TimerTask timerTask = new java.util.TimerTask() { 

      public void run() { 
       startWaitCursor(frame); 
      } 

     }; 
     final java.util.Timer timer = new java.util.Timer(); 
     timer.schedule(timerTask, DELAY_MS); 
     return timer; 
    } 

    public static void switchToNormalCursor(final javax.swing.JFrame frame, final java.util.Timer timer) { 
     timer.cancel(); 
     stopWaitCursor(frame); 
     stopEventTrap(frame); 
    } 

    private static void startWaitCursor(javax.swing.JFrame frame) { 
     frame.getGlassPane().setCursor(java.awt.Cursor.getPredefinedCursor(java.awt.Cursor.WAIT_CURSOR)); 
     frame.getGlassPane().addMouseListener(mouseAdapter); 
     frame.getGlassPane().setVisible(true); 
    } 

    private static void stopWaitCursor(javax.swing.JFrame frame) { 
     frame.getGlassPane().setCursor(java.awt.Cursor.getPredefinedCursor(java.awt.Cursor.DEFAULT_CURSOR)); 
     frame.getGlassPane().removeMouseListener(mouseAdapter); 
     frame.getGlassPane().setVisible(false); 
    } 

    private static void startEventTrap(javax.swing.JFrame frame) { 
     frame.getGlassPane().addMouseListener(mouseAdapter); 
     frame.getGlassPane().setVisible(true); 
    } 

    private static void stopEventTrap(javax.swing.JFrame frame) { 
     frame.getGlassPane().removeMouseListener(mouseAdapter); 
     frame.getGlassPane().setVisible(false); 
    } 

    private static final java.awt.event.MouseAdapter mouseAdapter = new java.awt.event.MouseAdapter() { 
    }; 

    public static void main(String[] args) { 
     javax.swing.SwingUtilities.invokeLater(new Runnable() { 

      public void run() { 
       new BusyCursorTest2(); 
      } 

     }); 

    } 

    private static final int DELAY_MS = 250; 

} 
  1. 运行SSCCE

  2. 点击按钮 “等待3秒”。它模拟一个昂贵的操作。鼠标光标将变为繁忙状态。

  3. 光标忙时,单击切换按钮“单击我”。如果三秒钟后,切换按钮改变其状态,则切换按钮接收到鼠标事件并且未被捕捉。

我希望当光标看起来很忙时,生成的鼠标(和其他)事件会被丢弃。

谢谢。

+0

不,大部分摆动组件(所有不同的面板及其内容等)都是由不同的开发人员完成的,而且这些组件可能会随时改变。我无法对这些挥杆组件做任何假设。我只能在rootpane上制作可见的玻璃窗,以防止他们获取事件。 –

+4

你有两个解决方案。 1)在工作者线程上放置昂贵的操作。 2)使用玻璃窗来阻止其他事件。 Swing的目的不是为了保护开发者的应用程序。 –

+1

不是很好的方式来改变或拆分一致性从EventQueue,但通过深入搜索这个论坛'EventQueue theQueue = getToolkit()。getSystemEventQueue();'不要为了得到,如果你手动发送任何事件到EDT,所有等待的线程将会丢失,并永远停留在现在的形式中,根本就不这样做, – mKorbel

回答

2

好的,我终于得到了一切工作。我发布了一个正确工作示例的SSCCE。诀窍是使用“javax.swing.SwingUtilities.invokeLater()”方法隐藏glasspane。将必要的代码包装在Runnable中,然后使用invokeLater调用它。在这种情况下,Swing会处理所有的鼠标事件(因为Glasspane会截取它们而没有任何反应),然后隐藏玻璃窗。这是SSCCE。

 
public class BusyCursorTest2 extends javax.swing.JFrame { 

    public BusyCursorTest2() { 

     javax.swing.JButton wait = new javax.swing.JButton("Wait 3 seconds"); 
     getContentPane().setLayout(new java.awt.GridLayout(2, 1, 0, 0)); 
     getContentPane().add(wait); 
     getContentPane().add(new javax.swing.JToggleButton("Click me")); 
     setTitle("Busy Cursor"); 
     setSize(300, 200); 
     setDefaultCloseOperation(javax.swing.JFrame.DISPOSE_ON_CLOSE); 
     setVisible(true); 

     wait.addActionListener(new java.awt.event.ActionListener() { 

      public void actionPerformed(java.awt.event.ActionEvent event) { 

       final java.util.Timer timer = switchToBusyCursor(BusyCursorTest2.this); 

       try { 
        //do something expensive in EDT or otherwise 
        try { 
         Thread.sleep(3000); 
        } catch (InterruptedException e) { 
         //do nothing 
        } 
       } finally { 
        switchToNormalCursorEventThread(BusyCursorTest2.this, timer); 
       } 

      } 

     }); 
    } 

    public static java.util.Timer switchToBusyCursor(final javax.swing.JFrame frame) { 
     startEventTrap(frame); 
     java.util.TimerTask timerTask = new java.util.TimerTask() { 

      public void run() { 
       startWaitCursor(frame); 
      } 

     }; 
     final java.util.Timer timer = new java.util.Timer(); 
     timer.schedule(timerTask, DELAY_MS); 
     return timer; 
    } 

    public static void switchToNormalCursorEventThread(final javax.swing.JFrame frame, final java.util.Timer timer) { 

     Runnable r = new Runnable() { 

      public void run() { 
       switchToNormalCursor(frame, timer); 
      } 

     }; 

     javax.swing.SwingUtilities.invokeLater(r); 

    } 

    public static void switchToNormalCursor(final javax.swing.JFrame frame, final java.util.Timer timer) { 
     timer.cancel(); 
     stopWaitCursor(frame); 
     stopEventTrap(frame); 
    } 

    private static void startWaitCursor(javax.swing.JFrame frame) { 
     frame.getGlassPane().setCursor(java.awt.Cursor.getPredefinedCursor(java.awt.Cursor.WAIT_CURSOR)); 
     frame.getGlassPane().addMouseListener(mouseAdapter); 
     frame.getGlassPane().setVisible(true); 
    } 

    private static void stopWaitCursor(javax.swing.JFrame frame) { 
     frame.getGlassPane().setCursor(java.awt.Cursor.getPredefinedCursor(java.awt.Cursor.DEFAULT_CURSOR)); 
     frame.getGlassPane().removeMouseListener(mouseAdapter); 
     frame.getGlassPane().setVisible(false); 
    } 

    private static void startEventTrap(javax.swing.JFrame frame) { 
     frame.getGlassPane().addMouseListener(mouseAdapter); 
     frame.getGlassPane().setVisible(true); 
    } 

    private static void stopEventTrap(javax.swing.JFrame frame) { 
     java.awt.Toolkit.getDefaultToolkit().getSystemEventQueue(); 
     frame.getGlassPane().removeMouseListener(mouseAdapter); 
     frame.getGlassPane().setVisible(false); 
    } 

    private static final java.awt.event.MouseAdapter mouseAdapter = new java.awt.event.MouseAdapter() { 
    }; 

    public static void main(String[] args) { 
     javax.swing.SwingUtilities.invokeLater(new Runnable() { 

      public void run() { 
       new BusyCursorTest2(); 
      } 

     }); 

    } 

    private static final int DELAY_MS = 250; 

} 

再说一遍,如果有可能的话一定不要封锁EDT。但是如果你必须这样做,你可以像上面那样有一个忙碌的游标。

欢迎任何评论。

1

阅读article

基本上,长时间运行的任务不应该在EDT上完成。 Java为SwingWorker提供了这样的任务。

我会进入更多的细节,但你不倾向于接受答案。

+0

我正在使用SwingWorker(自定义实现,因为我的代码应该是兼容JAVA 1.5)在我自己的代码。这是我无法控制的其他代码。感谢您的回答。 –

+0

嗯,我回去接受了我的问题的答案(其中一些我自己回答,所以我仍然接受)。对于那些从其他职位获得帮助的人,我回到任何一个我记忆中的岗位上。 –