开发者

How can I stop an SWT composite control from firing a MouseExit event when the mouse enters a component control?

开发者 https://www.devze.com 2022-12-22 01:19 出处:网络
I have subclassed org.eclipse.swt.widgets.Composite to create a new composite control. I want to capture MouseEnter and MouseExit events in this control but the problem I ha开发者_如何转开发ve is that

I have subclassed org.eclipse.swt.widgets.Composite to create a new composite control. I want to capture MouseEnter and MouseExit events in this control but the problem I ha开发者_如何转开发ve is that when the mouse is hovered over a component in the control (say, a Label) the MouseExit event is fired, even though the label is part of the whole Composite.

Is there any way to stop this event being fired? I only want to see the event if the mouse leaves the total boundary of the control. Here is some example code to show you what I mean.

public class MyControl extends Composite{

Label label;

public MyControl(Composite parent, String label) {
    super(parent, SWT.NONE);
    label = new Label(this,0);
    label.setText(label);

    this.addListener(SWT.MouseEnter, new Listener() {
        @Override
        public void handleEvent(Event event) {
            // handle this event
        }           
    });
    this.addListener(SWT.MouseExit, new Listener() {
        @Override
        public void handleEvent(Event event) {
            // handle this event
        }           
    });
}

}


You can simply put an logic in your event handler to see if the control is a child of your new control and ignore it. Something like the following: (I haven't tested the code, but I think this should work for you)

    this.addListener(SWT.MouseExit, new Listener() {
        @Override
        public void handleEvent(Event event) {
            for (Control control : ParentClass.this.getChildren()) {
                if (control == event.item)
                    return;
            }
            // handler logic goes here
        }           
    });


I solved the same problem (MouseExit is sent to a Composite when the mouse enters one of its children) with an event filter. Here's the code.

public class MouseTracker implements Listener {
    static MouseTracker instance;

    private static class Item {
        Composite composite;
        boolean inside;
        MouseTrackListener listener;
    }

    private List<Item> listeners = new ArrayList<>();

    private MouseTracker() {
    }

    public static MouseTracker getInstance() {
        if (instance == null)
            instance = new MouseTracker();
        return instance;
    }

    private void install() {
        Display.getCurrent().addFilter(SWT.MouseEnter, this);
        Display.getCurrent().addFilter(SWT.MouseExit, this);
        Display.getCurrent().addFilter(SWT.Resize, this);
    }

    private void uninstall() {
        Display.getCurrent().removeFilter(SWT.MouseEnter, this);
        Display.getCurrent().removeFilter(SWT.MouseExit, this);
        Display.getCurrent().removeFilter(SWT.Resize, this);
    }

    public void addMouseTrackListener(Composite c, MouseTrackListener listener) {
        if (listeners.isEmpty())
            install();
        Item i = new Item();
        i.composite = c;
        i.inside = false;
        i.listener = listener;
        listeners.add(i);
    }

    public void removeMouseTrackListener(Composite c, MouseTrackListener listener) {
        listeners.removeIf((i) -> i.composite == c && i.listener == listener);
        if (listeners.isEmpty())
            uninstall();
    }

    public void handleEvent(Event e) {
        boolean hasDisposed = false;
        for (Item i : listeners) {
            Composite c = i.composite;
            if (c.isDisposed())
                hasDisposed = true;
            else {
                Point p = Display.getCurrent().getCursorLocation();
                boolean containsMouse = c.getBounds().contains(c.getParent().toControl(p));
                if (i.inside != containsMouse) {
                    i.inside = containsMouse;
                    if (containsMouse)
                        i.listener.mouseEnter(new MouseEvent(e));
                    else
                        i.listener.mouseExit(new MouseEvent(e));
                }
            }
        }
        if (hasDisposed) {
            listeners.removeIf((i) -> i.composite.isDisposed());
            if (listeners.isEmpty())
                uninstall();
        }
    }
}
0

精彩评论

暂无评论...
验证码 换一张
取 消

关注公众号