Search code examples
javamultithreadingasynchronousswtmouseevent

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


Having a "next" Button, when I press keyboard enter key with the button selected, the widgetSelected event of the button is being repeatedly called once and once and doing a super fast next. It's exactly the behaviour I want, but only happens with keyboard enter key.

I want to have that behaviour with mouse click when holding the click. When trying to do the same with the mouse click, the behaviour is not the same, it only makes one event call, and when the click is end (UP). How to simulate the same behaviour with the mouse click?

I tried it doing this, but it blocks the UI (can't understand why) and mouseUp is never being called, it blocks forever in the 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;
        }
    }); 

Solution

  • The Runnable you give to asyncExec runs in the UI thread. You must never do any sort of wait in the UI thread as that will block the UI until it completes.

    So you cannot run a loop like this as it just blocks the UI. Since the loop never returns to the main SWT readAndDispatch loop no UI actions are done.

    Instead use the timerExec method of Display to schedule a Runnable to run after a given interval. This runnable should do one step of the action and use timerExec to schedule the next step later.