how to differentiate between a single click or double click on a table row in javafx

前端 未结 2 587
一向
一向 2021-01-26 11:44

I am trying to create a table in javafx that allows a user to click on a row to go to one page or double click the row to go to a different page. The problem is that the applica

2条回答
  •  长情又很酷
    2021-01-26 12:29

    I encountered the same requirement once and worked on developing a custom event dispatcher. The solution what @James_D provided is clean, simple and works great. But if you want to generalize this behavior on a large scale, you can define a new custom mouse event and an event dispatcher.

    The advantage of this approach is its usage will be just like other mouse events and can be handled in both event filters and handlers.

    Please check the below demo and the appropriate code:

    import javafx.animation.KeyFrame;
    import javafx.animation.Timeline;
    import javafx.application.Application;
    import javafx.event.*;
    import javafx.geometry.Pos;
    import javafx.scene.Node;
    import javafx.scene.Scene;
    import javafx.scene.input.MouseEvent;
    import javafx.scene.layout.HBox;
    import javafx.scene.layout.StackPane;
    import javafx.scene.shape.Rectangle;
    import javafx.stage.Stage;
    import javafx.util.Duration;
    
    public class DoubleClickEventDispatcherDemo extends Application {
    
        @Override
        public void start(Stage stage) throws Exception {
            Rectangle box1 = new Rectangle(150, 150);
            box1.setStyle("-fx-fill:red;-fx-stroke-width:2px;-fx-stroke:black;");
            addEventHandlers(box1, "Red Box");
    
            Rectangle box2 = new Rectangle(150, 150);
            box2.setStyle("-fx-fill:yellow;-fx-stroke-width:2px;-fx-stroke:black;");
            addEventHandlers(box2, "Yellow Box");
    
            HBox pane = new HBox(box1, box2);
            pane.setSpacing(10);
            pane.setAlignment(Pos.CENTER);
            addEventHandlers(pane, "HBox");
    
            Scene scene = new Scene(new StackPane(pane), 450, 300);
            stage.setScene(scene);
            stage.show();
    
            // THIS IS THE PART OF CODE SETTING CUSTOM EVENT DISPATCHER
            scene.setEventDispatcher(new DoubleClickEventDispatcher(scene.getEventDispatcher()));
        }
    
        private void addEventHandlers(Node node, String nodeId) {
            node.addEventFilter(MouseEvent.MOUSE_CLICKED, e -> System.out.println("" + nodeId + " mouse clicked filter"));
            node.addEventHandler(MouseEvent.MOUSE_CLICKED, e -> System.out.println("" + nodeId + " mouse clicked handler"));
    
            node.addEventFilter(CustomMouseEvent.MOUSE_DOUBLE_CLICKED, e -> System.out.println("" + nodeId + " mouse double clicked filter"));
            node.addEventHandler(CustomMouseEvent.MOUSE_DOUBLE_CLICKED, e -> System.out.println(nodeId + " mouse double clicked handler"));
        }
    
        /**
         * Custom MouseEvent
         */
        interface CustomMouseEvent {
            EventType MOUSE_DOUBLE_CLICKED = new EventType<>(MouseEvent.ANY, "MOUSE_DBL_CLICKED");
        }
    
        /**
         * Custom EventDispatcher to differentiate from single click with double click.
         */
        class DoubleClickEventDispatcher implements EventDispatcher {
    
            /**
             * Default delay to fire a double click event in milliseconds.
             */
            private static final long DEFAULT_DOUBLE_CLICK_DELAY = 215;
    
            /**
             * Default event dispatcher of a node.
             */
            private final EventDispatcher defaultEventDispatcher;
    
            /**
             * Timeline for dispatching mouse clicked event.
             */
            private Timeline clickedTimeline;
    
            /**
             * Constructor.
             *
             * @param initial Default event dispatcher of a node
             */
            public DoubleClickEventDispatcher(final EventDispatcher initial) {
                defaultEventDispatcher = initial;
            }
    
            @Override
            public Event dispatchEvent(final Event event, final EventDispatchChain tail) {
                final EventType type = event.getEventType();
                if (type == MouseEvent.MOUSE_CLICKED) {
                    final MouseEvent mouseEvent = (MouseEvent) event;
                    final EventTarget eventTarget = event.getTarget();
                    if (mouseEvent.getClickCount() > 1) {
                        if (clickedTimeline != null) {
                            clickedTimeline.stop();
                            clickedTimeline = null;
                            final MouseEvent dblClickedEvent = copy(mouseEvent, CustomMouseEvent.MOUSE_DOUBLE_CLICKED);
                            Event.fireEvent(eventTarget, dblClickedEvent);
                        }
                        return mouseEvent;
                    }
                    if (clickedTimeline == null) {
                        final MouseEvent clickedEvent = copy(mouseEvent, mouseEvent.getEventType());
                        clickedTimeline = new Timeline(new KeyFrame(Duration.millis(DEFAULT_DOUBLE_CLICK_DELAY), e -> {
                            Event.fireEvent(eventTarget, clickedEvent);
                            clickedTimeline = null;
                        }));
                        clickedTimeline.play();
                        return mouseEvent;
                    }
                }
                return defaultEventDispatcher.dispatchEvent(event, tail);
            }
    
            /**
             * Creates a copy of the provided mouse event type with the mouse event.
             *
             * @param e         MouseEvent
             * @param eventType Event type that need to be created
             * @return New mouse event instance
             */
            private MouseEvent copy(final MouseEvent e, final EventType eventType) {
                return new MouseEvent(eventType, e.getSceneX(), e.getSceneY(), e.getScreenX(), e.getScreenY(),
                        e.getButton(), e.getClickCount(), e.isShiftDown(), e.isControlDown(), e.isAltDown(),
                        e.isMetaDown(), e.isPrimaryButtonDown(), e.isMiddleButtonDown(),
                        e.isSecondaryButtonDown(), e.isSynthesized(), e.isPopupTrigger(),
                        e.isStillSincePress(), e.getPickResult());
            }
        }
    }
    

提交回复
热议问题