【问题标题】:Starting "asyncExec" in Mouse Down Event results in blocking behavior在鼠标按下事件中启动“asyncExec”会导致阻塞行为
【发布时间】:2018-11-09 19:55:47
【问题描述】:

有一个“下一个”按钮,当我在选择按钮的情况下按下键盘输入键时,按钮的 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;
        }
    }); 

【问题讨论】:

  • 从“阻塞”问题开始。此外,如果有多个线程,变量必须是volatile 以确保它在线程之间“可见”。
  • @user2864740 你能在你的提案中发布一些示例代码吗?不明白你想让我做什么
  • 除了使用volatile boolean mouseDown之外我没有其他建议[我更喜欢使用明确的线程,但我也是这样的“老派”] :) 希望有人能提供有用的反馈可能的 UI 异步交互。

标签: java multithreading asynchronous swt mouseevent


【解决方案1】:

您提供给asyncExecRunnable 在UI 线程中运行。您必须绝不在 UI 线程中进行任何形式的等待,因为这会阻塞 UI,直到它完成。

所以你不能像这样运行循环,因为它只会阻塞 UI。由于循环永远不会返回到主 SWT readAndDispatch 循环,因此不会执行任何 UI 操作。

改为使用DisplaytimerExec 方法来安排Runnable 在给定时间间隔后运行。此可运行对象应该执行该操作的一个步骤,并使用timerExec 安排稍后的下一步。

【讨论】:

  • 嗨@greg-449 感谢您的想法,但是如何在 mouseUp 事件之前实现一系列 timerExec 方法?如果我在原来的 timerExec 中调用一个新的 timerExec,我只会得到两次对我的函数的调用,如果我总是调用 timerExecs,我的函数就会被调用,我会得到一个 timerExecs 的无限循环。
  • 好的@greg-449 我现在明白你了。您的意思是当我的 mouseDown 布尔值为 true 并在 mouseUp 事件上将其设置为 false 时,使用递归调用启动 timerExec 的方法。它使用它。谢谢你的好主意:)
  • mmmm 问题是,如果我这样做,即使单击一下,我也会变得超快:|嗯,我敢肯定一定是解决这个问题的简单方法......
  • 好吧,我想我用一种新方法解决了它,如果布尔值在 1 秒后仍然为真,则尝试启动 100ms 方法,行为与我的预期相似,非常感谢
【解决方案2】:

我记得几天前还有一个关于长鼠标单击行为的问题,但我再也找不到了。在我尝试在 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")));

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2019-02-18
    • 1970-01-01
    • 1970-01-01
    • 2011-12-12
    • 2013-04-04
    • 1970-01-01
    • 2013-07-23
    相关资源
    最近更新 更多