Javafx 2 click and double click
我想知道是否可以在JavaFX2中检测到双击?如何?
我想在单击和双击之间进行不同的活动。
谢谢
是的,您可以检测到单次、双次甚至多次单击:
1 2 3 4 5 6 7 8 9 10 | myNode.setOnMouseClicked(new EventHandler<MouseEvent>() { @Override public void handle(MouseEvent mouseEvent) { if(mouseEvent.getButton().equals(MouseButton.PRIMARY)){ if(mouseEvent.getClickCount() == 2){ System.out.println("Double clicked"); } } } }); |
这是另一段代码,如果您必须区分单击和双击,并且在这两种情况下都必须采取特定的操作,则可以使用它。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 | import java.util.concurrent.ScheduledFuture; import java.util.concurrent.ScheduledThreadPoolExecutor; import java.util.concurrent.TimeUnit; import javafx.application.Application; import javafx.event.EventHandler; import javafx.scene.Scene; import javafx.scene.input.MouseButton; import javafx.scene.input.MouseEvent; import javafx.scene.layout.StackPane; import javafx.stage.Stage; public class DoubleClickDetectionTest extends Application { boolean dragFlag = false; int clickCounter = 0; ScheduledThreadPoolExecutor executor; ScheduledFuture<?> scheduledFuture; public DoubleClickDetectionTest() { executor = new ScheduledThreadPoolExecutor(1); executor.setRemoveOnCancelPolicy(true); } public static void main(String[] args) { launch(args); } @Override public void start(Stage primaryStage) throws Exception { StackPane root = new StackPane(); primaryStage.setScene(new Scene(root, 400, 400)); primaryStage.show(); root.setOnMouseDragged(new EventHandler<MouseEvent>() { @Override public void handle(MouseEvent e) { if (e.getButton().equals(MouseButton.PRIMARY)) { dragFlag = true; } } }); root.setOnMouseClicked(new EventHandler<MouseEvent>() { @Override public void handle(MouseEvent e) { if (e.getButton().equals(MouseButton.PRIMARY)) { if (!dragFlag) { System.out.println(++clickCounter +"" + e.getClickCount()); if (e.getClickCount() == 1) { scheduledFuture = executor.schedule(() -> singleClickAction(), 500, TimeUnit.MILLISECONDS); } else if (e.getClickCount() > 1) { if (scheduledFuture != null && !scheduledFuture.isCancelled() && !scheduledFuture.isDone()) { scheduledFuture.cancel(false); doubleClickAction(); } } } dragFlag = false; } } }); } @Override public void stop() { executor.shutdown(); } private void singleClickAction() { System.out.println("Single-click action executed."); } private void doubleClickAction() { System.out.println("Double-click action executed."); } } |
P.Pandey的回答是最简单的方法,它实际上区分了单点击和双击,但它不适用于我。首先,函数"currentTimeMillis"已经返回毫秒,所以将其除以1000似乎是不必要的。下面的版本以更一致的方式为我工作。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 | @Override public void handle(MouseEvent t) { long diff = 0; currentTime=System.currentTimeMillis(); if(lastTime!=0 && currentTime!=0){ diff=currentTime-lastTime; if( diff<=215) isdblClicked=true; else isdblClicked=false; } lastTime=currentTime; System.out.println("IsDblClicked()"+isdblClicked); //use the isdblClicked flag... } |
以下是我如何实现双击
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | if (e.getEventType().equals(MouseEvent.MOUSE_CLICKED) && !drag_Flag) { long diff = 0; if(time1==0) time1=System.currentTimeMillis(); else time2=System.currentTimeMillis(); if(time1!=0 && time2!=0) diff=time2-time1; if((diff/1000)<=215 && diff>0) { isdblClicked=true; } else { isdblClicked=false; } System.out.println("IsDblClicked()"+isdblClicked); |
}
由于默认情况下无法区分单击和双击,因此我们使用以下方法:
在单击时,我们将单击操作包装在可中止的可运行文件中。这个runnable在执行之前等待一定的时间(即
同时,如果发生第二次单击(即双击),则会中止单击操作,只执行双击操作。
这样,可以执行单击或双击操作,但不能同时执行这两种操作。
以下是完整代码。要使用它,只有三条
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 | private static final int SINGLE_CLICK_DELAY = 250; private ClickRunner latestClickRunner = null; private class ClickRunner implements Runnable { private final Runnable onSingleClick; private boolean aborted = false; public ClickRunner(Runnable onSingleClick) { this.onSingleClick = onSingleClick; } public void abort() { this.aborted = true; } @Override public void run() { try { Thread.sleep(SINGLE_CLICK_DELAY); } catch (InterruptedException e) { e.printStackTrace(); } if (!aborted) { System.out.println("Execute Single Click"); Platform.runLater(() -> onSingleClick.run()); } } } private void init() { container.setOnMouseClicked(me -> { switch (me.getButton()) { case PRIMARY: if (me.getClickCount() == 1) { System.out.println("Single Click"); latestClickRunner = new ClickRunner(() -> { // TODO: Single-left-click operation }); CompletableFuture.runAsync(latestClickRunner); } if (me.getClickCount() == 2) { System.out.println("Double Click"); if (latestClickRunner != null) { System.out.println("-> Abort Single Click"); latestClickRunner.abort(); } // TODO: Double-left-click operation } break; case SECONDARY: // TODO: Right-click operation break; default: break; } }); } |
坚持Java SE 8 lambda表达式将看起来像这样:
1 2 3 4 5 | node.setOnMouseClicked(event -> { if(event.getButton().equals(MouseButton.PRIMARY) && event.getClickCount() == 2) { handleSomeAction(); } }); |
一旦你习惯了lambda表达式,它们最终会比原始的类实例化和重写(x)方法更容易理解。-在我看来