JavaFX:对Single,Double和Triple Click做出反应

mel*_*ldi 2 mouseclick-event javafx-8

我正在尝试配置某些操作以响应鼠标点击次数.在我看来,单击和三击被检测并应用.但双击并不真正起作用.我尝试过这样的事情:

if (doubleClick)
else if (tripleClick)
else if (singleClick).
Run Code Online (Sandbox Code Playgroud)

检查的顺序也没有帮助,双击的操作永远不会被触发,因为单击的操作首先被触发.关于如何做到这一点的任何想法?

Jam*_*s_D 8

假设你正在做类似的事情

if (mouseEvent.getClickCount()==1) 
Run Code Online (Sandbox Code Playgroud)

等等,那可能不是你想的那样.MouseEvent.getClickCount()只返回"小"区域和"小"时间内发生的点击次数."小"是(故意)没有定义.

所以双击只需两次点击.第一个返回1 getClickCount(),然后第二个返回2.类似地,三次点击是三次点击:第一个返回1,下一个返回2,第三个3.您可以使用一段非常简单的代码对此进行测试:

import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.layout.Pane;
import javafx.stage.Stage;

public class ClickCountTest extends Application {

    @Override
    public void start(Stage primaryStage) {
        Pane root = new Pane();
        root.setOnMouseClicked(event -> System.out.println(event.getClickCount()));
        primaryStage.setScene( new Scene(root, 250, 150) );
        primaryStage.show();
    }

    public static void main(String[] args) {
        launch(args);
    }
}
Run Code Online (Sandbox Code Playgroud)

如果单击,您将看到输出"1".如果你双击,你会看到一个"1"后跟一个"2".

如果它是双击(或三击)的一部分,则没有内置方法可以忽略第一次单击.显然,问题在于,在第一次点击时,没有办法知道在没有某种时序的情况下是否会出现另一次点击,这会变得非常复杂并且会导致响应任何鼠标点击的延迟.

有一段时间有人谈论实现一种onClickSequenceFinished类型的事件,因此您可以监听点击序列完成事件,然后查询该事件以查找点击次数,而不是监听鼠标点击事件.最后,决定不支持这一点,因为用例不被认为是良好的UI编程实践.

这样做的原因是,例如,双击以排除单击操作是一个非常糟糕的主意.如果用户双击太慢,则会无意中调用单击操作(两次).因此,如果您同时支持双击和单击操作,则应选择操作,以便在调用双击操作时调用单击操作是有意义的.典型示例是a ListView,双击列表元素打开"详细信息"编辑器,然后单击选择该项.对于正在编辑的项目也是有意义的,因此双击操作意味着单击操作.

换句话说,如果双击动作被设计为排除单击动作,那么它被认为是一个糟糕的设计,并且不直接支持该习语.您应该考虑使用修饰键而不是点击计数来进行这种区分.

更新: 如果你真的想通过这样的点击计数区分事件(我真的不推荐它),那么你可以使用像a这样的东西PauseTransition来实现计时器.就像是:

import javafx.animation.PauseTransition;
import javafx.application.Application;
import javafx.beans.property.IntegerProperty;
import javafx.beans.property.SimpleIntegerProperty;
import javafx.scene.Scene;
import javafx.scene.layout.Pane;
import javafx.stage.Stage;
import javafx.util.Duration;

public class ClickCountTest extends Application {

    @Override
    public void start(Stage primaryStage) {

        // This value may need tuning:
        Duration maxTimeBetweenSequentialClicks = Duration.millis(500);

        PauseTransition clickTimer = new PauseTransition(maxTimeBetweenSequentialClicks);
        final IntegerProperty sequentialClickCount = new SimpleIntegerProperty(0);
        clickTimer.setOnFinished(event -> {
            int count = sequentialClickCount.get();
            if (count == 1) System.out.println("Single click");
            if (count == 2) System.out.println("Double click");
            if (count == 3) System.out.println("Triple click");
            if (count > 3) System.out.println("Multiple click: "+count);
            sequentialClickCount.set(0);
        });

        Pane root = new Pane();
        root.setOnMouseClicked(event -> {
            sequentialClickCount.set(sequentialClickCount.get()+1);
            clickTimer.playFromStart();
        });
        primaryStage.setScene( new Scene(root, 250, 150) );
        primaryStage.show();
    }

    public static void main(String[] args) {
        launch(args);
    }
}
Run Code Online (Sandbox Code Playgroud)

这也可能是Tomas Mikula的ReactFX框架的一个很好的用例,(也见他的博客文章).


Jef*_*her 5

如果要检测每个不同的点击次数,可以使用switch语句.

import javafx.application.Application;
import javafx.scene.Group;
import javafx.scene.Scene;
import javafx.scene.paint.Color;
import javafx.scene.shape.Circle;
import javafx.stage.Stage;

/**
 *
 * @author jeffreyguenther
 */
public class ListTest extends Application{

    @Override
    public void start(Stage stage) throws Exception {
        Circle c = new Circle();
        c.setRadius(100);
        c.setCenterX(100);
        c.setCenterY(100);
        c.setFill(Color.AQUA);
        c.setStroke(Color.BLACK);
        c.setStrokeWidth(3);

        c.setOnMousePressed((e) ->{

            switch(e.getClickCount()){
                case 1:
                    System.out.println("One click");
                    break;
                case 2:
                    System.out.println("Two clicks");
                    break;
                case 3:
                    System.out.println("Three clicks");
                    break;
            }

        });

        stage.setScene(new Scene(new Group(c)));
        stage.show();
    }

    public static void main(String[] args) {
        launch(args);
    }
}
Run Code Online (Sandbox Code Playgroud)

然后,当您单击,双击和三次单击时,将给出以下输出:

One click
Two clicks
Three clicks
Run Code Online (Sandbox Code Playgroud)

您可以使用case语句来确定要处理的计数.例如,如果您只想处理双击和三击,则可以删除第一个案例.