java swing清除事件队列

San*_*ari 5 java swing eventqueue event-dispatch-thread

是否可以以标准方式执行此操作?

这是场景.

  1. 开始在EDT中做一些昂贵的事情(EDT被阻止,直到昂贵的操作结束).

  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. 光标处于忙碌状态时,单击切换按钮"单击我".如果在三秒钟后,切换按钮改变其状态,则切换按钮接收到鼠标事件并且没有被捕获.

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

谢谢.

San*_*ari 5

好的,我终于让一切正常工作了。我正在发布 SSCCE 以获得正确工作的示例。诀窍是使用“javax.swing.SwingUtilities.invokeLater()”方法隐藏玻璃窗格。将必要的代码包装在 Runnable 中,然后使用 invokeLater 调用它。在这种情况下,Swing 处理所有鼠标事件(因为玻璃板拦截了它们,所以什么也没发生),然后隐藏玻璃板。这里是 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(wait);
        getContentPane().add(new javax.swing.JToggleButton("点击我"));
        setTitle("忙光标");
        setSize(300, 200);
        setDefaultCloseOperation(javax.swing.JFrame.DISPOSE_ON_CLOSE);
        设置可见(真);

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

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

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

                尝试 {
                    // 在 EDT 或其他方式中做一些昂贵的事情
                    尝试 {
                        线程睡眠(3000);
                    } catch (InterruptedException e) {
                        //没做什么
                    }
                } 最后 {
                    switchToNormalCursorEventThread(BusyCursorTest2.this, timer);
                }

            }

        });
    }

    公共静态java.util.Timer switchToBusyCursor(最终javax.swing.JFrame框架){
        开始事件陷阱(帧);
        java.util.TimerTask timerTask = new java.util.TimerTask() {

            公共无效运行(){
                startWaitCursor(frame);
            }

        };
        final java.util.Timer timer = new java.util.Timer();
        timer.schedule(timerTask, DELAY_MS);
        返回计时器;
    }

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

        可运行 r = 新可运行(){

            公共无效运行(){
                switchToNormalCursor(frame, timer);
            }

        };

        javax.swing.SwingUtilities.invokeLater(r);

    }

    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框架){
        java.awt.Toolkit.getDefaultToolkit().getSystemEventQueue();
        frame.getGlassPane().removeMouseListener(mouseAdapter);
        frame.getGlassPane().setVisible(false);
    }

    私有静态最终 java.awt.event.MouseAdapter mouseAdapter = new java.awt.event.MouseAdapter() {
    };

    公共静态无效主(字符串 [] args){
        javax.swing.SwingUtilities.invokeLater(new Runnable() {

            公共无效运行(){
                新的 BusyCursorTest2();
            }

        });

    }

    私有静态最终 int DELAY_MS = 250;

}

同样,如果可能的话,EDT 一定不能被阻止。但是如果必须的话,你可以有一个工作繁忙的光标,如上所述。

欢迎提出任何意见。