SWT MouseDown event too dominant for custom selecting controls

 ̄綄美尐妖づ 提交于 2019-12-12 04:58:35

问题


I have made the UI/Editor you can see in the picture below. The Text is displayed by StyledTexts. The black lines are custom borders that are in fact Labels with lines drawn on them.

Now my goal is to provide a selection that allows the user to select the Controls to delete them or add others to them. The second image shows a example selection. So started with all kinds of MouseEvents this is more complicated than I initially thought.

When the MouseDown event is fired on any Control I am not able to track any other Controls that the user wants to select because the MouseMove event contains the same control that fired the MouseDown event until the mouse gets released. I need to track to ongoing selection to provide the visual feedback for the selected Controls. The code below shows a minimal example to demonstrate the behavior.

public class Tester {

    public static void main(String[] args)
    {
        Display display = new Display();
        final Shell shell = new Shell(display);
        shell.setLayout(new FillLayout());
        shell.setText("Stackoverflow");

        Composite comp = new Composite(shell, SWT.NONE);
        comp.setLayout(new GridLayout(1, true));
        SelectionListener listener = new SelectionListener();

        StyledText text = new StyledText(comp, SWT.NONE);
        text.setText("first text");
        attachListener(text, listener);
        text = new StyledText(comp, SWT.NONE);
        text.setText("second text");
        attachListener(text, listener);


        shell.pack();
        shell.open();
        while (!shell.isDisposed())
        {
            if (!display.readAndDispatch())
                display.sleep();
        }
        display.dispose();
    }

    private static void attachListener(Control control, Listener listener) {
        if(control != null && !control.isDisposed()){
            control.addListener(SWT.MouseDown, listener);
            control.addListener(SWT.MouseMove, listener);
            control.addListener(SWT.MouseEnter, listener);
            control.addListener(SWT.MouseUp, listener);
        }
    }

    static class SelectionListener implements Listener {

        Event lastEvent = null;

        @Override
        public void handleEvent(Event event) {
            switch(event.type){

            case SWT.MouseDown:
                lastEvent = event;
                break;

            case SWT.MouseMove:
                if(lastEvent != null){
                    if(event.widget == lastEvent.widget)
                        System.out.println("the same!!!");
                    else
                        System.out.println("not the same!!!");
                }
                break;

            case SWT.MouseEnter:
                //this also does not fire when MouseDown is fired
                System.out.println("entering");
                break;

            case SWT.MouseUp:
                lastEvent = null;
                break;
            }
        }

    }
}

So basically I am reaching out for help. Maybe there is a better/simpler way to achieve this. I was also trying to figure out how swt is doing this in tables or other controls that support multiple selection. But its hard to find the specific code or they call native methods for nativ controls such as tables. So if anyone has an idea please share.


回答1:


I found a solution for my problem. You can post a MouseUp event yourself. After that all events are coming through again. The only difficult part is to distinguish between your own custom event and a normal user/system event. I was able create/find some criteria to identify the custom event. The following code/doc explains this in more detail:

/**
     * Sets up a custom {@code SWT.MouseUp} event and fires it. This is needed because a {@code SWT.MouseDown} is consuming all
     * other events until a {@code SWT.MouseUp} event is fired. This means that it is not possible to get a e.g. 
     * {@code SWT.MouseEnter} event when entering a certain StyledText which is needed for selection. Therefore a custom {@code SWT.MouseUp} 
     * event is fired to simulate the releasing of the button on system level so that all other events can come through again. The real problem here
     * is to distinguish between the custom event for simulation and a normal event produced by the user. Firing the event via Display.post(Event)
     * does not fire the handed over event parameter. The system actually creates a new event instance. Therefore 2 criteria are used to distinguish the custom event:
     *  <ul>
     *      <ol>1. The selection can only be started by dragging a border control. 
     *          A {@code SWT.DragDetect} event starts the hole selection process. All events coming in before this event are ignored.</ol>
     *      <ol>2. The actual distinguishing of the {@code SWT.MouseUp} is performed on the cursor coordinates and the referenced/dragged {@code widget}.
     *          The dragging event has to be started on this widget.</ol>
     *  </ul>
     * @param the starting {@code SWT.DragDetect} event
     * @see #isCustomMouseUpEvent(Event)
     */
    private void fireCustomMouseUpEvent(Event dragDetectEvent){
        customMouseUpEvent = new Event();
        customMouseUpEvent.type = SWT.MouseUp;
        customMouseUpEvent.button = 1; //left mouse button
        customMouseUpEvent.widget = dragDetectEvent.widget;

        if(dragDetectEvent.widget instanceof Control){
            startingControl = (Control) dragDetectEvent.widget;
            //get cursor location relative to widget to be comparable later with the event fired by the system
            Point cursorLocation = startingControl.toControl(startingControl.getDisplay().getCursorLocation());
            customMouseUpEvent.x = cursorLocation.x;
            customMouseUpEvent.y = cursorLocation.y;
        }

        /*
         * note: set attributes like Event.data or Event.x are not present 
         * in the actually firing event. SWT or the system is creating a complete new
         * event instance without those manually added information.
         */
//      mouseUpEvent.data = SELECTION_START_EVENT_IDENTIFIER;
        if(dragDetectEvent.widget.getDisplay().post(customMouseUpEvent))
            System.out.println("custom MouseUp event fired!");
    }

    private boolean isCustomMouseUpEvent(Event event) {
        return customMouseUpEvent != null && event.widget == customMouseUpEvent.widget && 
                customMouseUpEvent.x == event.x && customMouseUpEvent.y == event.y;
    }


来源:https://stackoverflow.com/questions/44526366/swt-mousedown-event-too-dominant-for-custom-selecting-controls

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!