如何在javafx中的表行上单击还是双击之间进行区分 [英] how to differentiate between a single click or double click on a table row in javafx

查看:85
本文介绍了如何在javafx中的表行上单击还是双击之间进行区分的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试在javafx中创建一个表,该表允许用户单击行以转到一个页面或双击该行以转到另一个页面.问题在于该应用程序注册了单击事件,但没有等待查看是否还有另一个双击事件.有没有办法让程序等待,看看是否还有另外的点击?

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 application registers the event of the single click, but does not wait to see if there is another double click. Is there a way to have the program wait and see if there is another click?

到目前为止,我的情况类似于类似的东西

what i have so far looks similar to something like

TableView searchResults;
ObservableList<MovieRow> rows = FXCollections.observableArrayList();

private TableColumn<MovieRow, String> title;
title.setCellValueFactory(new PropertyValueFactory<>("mTitle"));

rows.add(new MovieRow("The cat in the hat"));

searchResults.setItems(rows);

searchResults.setRowFactory(tv -> {
    TableRow<MovieRow> row = new TableRow<>();
    row.setOnMouseClicked(event -> {
        MovieRow tempResult = row.getItem();

        if (event.getClickCount() == 1) {
            System.out.println(tempResult.getMTitle + " was clicked once");
        }else{
            System.out.println(tempResult.getMTitle + " was clicked twice");
        }
    });
    return row;
});

public class MovieRow{
    private String mTitle;
    
    public MovieRow(String title){
           mTitle = title;
    }

    public String getMTitle() {
            return mTitle;
    }
}

实际输出

single click: The cat in the hat was clicked once
double click: The cat in the hat was clicked once

所需的输出

single click: The cat in the hat was clicked once
double click: The cat in the hat was clicked twice

我只发现了自己处理双击或自己单击的结果,但没有两者都得到,所以我不确定这是否可能.任何帮助将非常感激.谢谢.

I've only found results on handling double clicks by themselves or single clicks by themselves but not having both, so I'm not sure if this is even possible. Any help would be much appreciated. Thanks.

推荐答案

我曾经遇到过相同的要求,并且致力于开发自定义事件分配器. @James_D提供的解决方案干净,简单并且效果很好.但是,如果要大规模推广此行为,则可以定义一个新的自定义鼠标事件和一个事件分配器.

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<MouseEvent> 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<? extends Event> 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<? extends MouseEvent> 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());
        }
    }
}

这篇关于如何在javafx中的表行上单击还是双击之间进行区分的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆