在鼠标按下事件中启动 "asyncExec" 会导致阻塞行为

Starting "asyncExec" in Mouse Down Event results in blocking behavior

有一个“下一个”按钮,当我在选择按钮的情况下按下键盘回车键时,按钮的 widgetSelected 事件被一次又一次地重复调用,并且下一个超级快。这正是我想要的行为,但只发生在键盘输入键上。

我希望在按住鼠标单击时具有鼠标单击的行为。当尝试用鼠标点击做同样的事情时,行为是不一样的,它只进行一次事件调用,当点击结束时(UP)。如何用鼠标点击来模拟同样的行为?

我试过这样做,但它会阻塞 UI(不明白为什么)并且 mouseUp 永远不会被调用,它永远阻塞在 while:

    button.addMouseListener(new MouseAdapter() {
        boolean mouseDown;
        @Override
        public void mouseDown(MouseEvent e) {
            System.out.println("mouseDown");
            mouseDown = true;
            Display.getDefault().asyncExec(new Runnable() {
                @Override
                public void run() {
                    while (mouseDown) {
                        System.out.println("Doing next in mouseDown");
                        next(composite, label_1);
                        synchronized(this){
                            try {
                                wait(100);
                            } catch (InterruptedException e) {
                                e.printStackTrace();
                            }
                        }
                    }
                }
            });
            
        }
        @Override
        public void mouseUp(MouseEvent e) {
            System.out.println("mouseUp");
            mouseDown = false;
        }
    }); 

您在 UI 线程中给 asyncExec 运行 的 Runnable。您必须 永远不要 在 UI 线程中进行任何类型的等待,因为这会阻塞 UI 直到它完成。

所以你不能 运行 这样的循环,因为它只会阻塞 UI。由于循环从不 returns 到主 SWT readAndDispatch 循环没有 UI 操作完成。

而是使用 DisplaytimerExec 方法在给定时间间隔后安排 Runnable 到 运行。此 运行nable 应该执行操作的一个步骤,然后使用 timerExec 安排下一步。

我记得几天前还有一个关于鼠标长按行为的问题,但我找不到了。在我尝试在 UI 线程中使用 asyncExec 失败后,我将这段基于 greg-449 解决方案的代码用于使用 timerExec 方法。 :)

    button.addMouseListener(new MouseAdapter() {
        boolean mouseDown;

        @Override
        public void mouseDown(MouseEvent e) {
            mouseDown = true;
            Display.getCurrent().timerExec(1000, () -> {
                if (mouseDown) {
                    button.notifyListeners(SWT.Selection, new Event());
                    button.notifyListeners(SWT.MouseDown, new Event());
                }
            });
        }

        @Override
        public void mouseUp(MouseEvent e) {
            mouseDown = false;
        }
    });

    button.addSelectionListener(SelectionListener.widgetSelectedAdapter(
            e -> System.out.println("Do next")));