鼠标点击事件-JavaFX:对单次、双击和三次点击作出反应



我正在尝试配置某些操作以响应鼠标点击次数。在我看来,单次点击和三次点击都会被检测到并应用。但是双击并不能真正起作用。我试着做一些类似的事情:

if (doubleClick)
else if (tripleClick)
else if (singleClick).

检查顺序也没有帮助,双击的操作从未被触发,因为单击的操作首先被触发。有什么想法吗?

假设您正在执行类似的操作

if (mouseEvent.getClickCount()==1) 

等等,那么它可能并没有按照你的想法去做。MouseEvent.getClickCount()只是返回在"小"区域和"小"时间内发生的点击次数。"小"(故意)没有定义。

所以双击就是两次点击。对于getClickCount(),第一个返回1,然后第二个返回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);
    }
}

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

如果第一次点击是双击(或三次)的一部分,则没有内置的方法可以忽略它。显然,问题是,在第一次点击时,如果没有某种时间,就无法知道是否会有另一次点击,这会变得非常复杂,并会迫使对任何鼠标点击的响应延迟。

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

原因是,双击以排除单击的操作是一个非常糟糕的主意。如果用户双击太慢,那么他们会无意中调用单击操作(两次)。因此,如果您同时支持双击和单击操作,那么应该选择这些操作,以便在任何时候调用双击操作时都可以调用单击操作。典型的例子是ListView,双击列表元素会打开一个"详细信息"编辑器,单击即可选择该项目。也可以选择正在编辑的项目,因此双击操作意味着单击操作。

换句话说,如果双击操作被设计为排除单击操作,并且不直接支持该习惯用法,那么这被认为是一种糟糕的设计。对于这种区别,您应该考虑使用修改键而不是单击次数。

更新:如果真的想像这样通过点击次数来区分事件(我不建议这样做),那么你可以使用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);
    }
}

这可能也是TomasMikula的ReactFX框架的一个很好的用例(也可以参见他的博客文章)。

如果您想检测每个不同的点击次数,可以使用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);
    }
}

然后,当你单次、两次和三次点击时,就会给出这个输出:

One click
Two clicks
Three clicks

您可以使用case语句来确定要处理的计数。例如,如果您只想处理双击和三次单击,则可以删除第一种情况。

最新更新