60

JavaFX 2でダブルクリックを検出できたかどうか知りたいですか?そしてどうやって ?

クリックとダブルクリックで違うイベントを作りたいです。

ありがとう

4

11 に答える 11

102

はい、1回、2回、さらには複数回のクリックを検出できます。

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");
            }
        }
    }
});

MouseButton.PRIMARY左(通常)マウスボタンがイベントをトリガーするかどうかを決定するために使用されます。のAPIを読んで、getClickCount()シングルまたはダブル以外のクリック数が複数ある可能性があると結論付けます。ただし、シングルクリックイベントとダブルクリックイベントを区別するのは難しいと思います。ダブルクリックの最初のクリック数によって、1つのイベントも発生するためです。

于 2012-06-08T14:30:33.903 に答える
7

シングルクリックとダブルクリックを区別し、どちらの場合も特定のアクションを実行する必要がある場合に使用できる別のコードを次に示します。

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.");
    }
}
于 2016-03-27T09:26:31.997 に答える
3

P. Pandey による応答は、シングル クリックとダブル クリックを実際に区別する最も単純なアプローチですが、私にはうまくいきませんでした。1 つには、関数「currentTimeMillis」は既にミリ秒を返しているため、1000 で割る必要はないようです。以下のバージョンは、より一貫した方法で機能しました。

 @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...   
}
于 2016-07-18T03:18:40.693 に答える
0

私は同じ問題を抱えていましたが、シングルクリックとダブルクリックが basic で区別されていることに気付きました:

    Button btn = new Button("Double click me too");
    btn.setOnMousePressed(mouseEvent -> {
        // CLICK catches
        if (mouseEvent.getClickCount() == 1) {
            System.out.println("Button clicked");
        } else if (mouseEvent.getClickCount() == 2)
            System.out.println("Button double clicked");
    });

ただし、「シングル」クリックはダブルクリックの一部としてキャッチされます。したがって、コンソールに次のように表示されます。 ここに画像の説明を入力

主に @markus-weninger の回答を使用して、Button2 つの新しいEventHandlersを公開するように拡張する Class を作成しました。

  • setOnMouseSingleClicked(EventHandler<MouseEvent> eventHandler)
  • setOnMouseDoubleClicked(EventHandler<MouseEvent> eventHandler)

したがって、以下の完全なコード例では、最後のボタンをダブルクリックすると、次のようになります。 ここに画像の説明を入力

心に留めておいてください:

  1. 明らかな欠点は、 (Kleopatraが述べたように、OSに応じて設定する必要がある公開された変数)でキャッチされた1回のクリックでさえsetOnMouseSingleClicked遅延することです。singleClickDelayMillis
  2. もう 1 つの注目すべき事実は、私が拡張したことButtonですNodeここに画像の説明を入力
  3. setOnMousePressed最後のコメントとして、既存のを使用するのではなく、新しい EventHandler を追加するsetOnMouseReleasedsetOnMouseClicked、開発者がこれらの便利な を完全に実装できるようにすることにしましたEventHandler。たとえば、ボタンをクリックすると、singleClickDelayMillis. ただし、これは、両方を実装するsetOnMouseClickedと、ダブルクリックでも起動されることを意味します...注意してください。

コードは次のとおりです。

import java.util.concurrent.CompletableFuture;

import javafx.application.Application;
import javafx.application.Platform;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.Label;
import javafx.scene.input.MouseEvent;
import javafx.scene.layout.VBox;
import javafx.stage.Stage;
import javafx.beans.property.ObjectProperty;
import javafx.event.EventHandler;
import javafx.beans.property.SimpleObjectProperty;

public class DblClickCatchedWithoutSingleClick extends Application {

public class ButtonWithDblClick extends Button {

    private long        singleClickDelayMillis  = 250;
    private ClickRunner latestClickRunner       = null;

    private ObjectProperty<EventHandler<MouseEvent>>    onMouseSingleClickedProperty    = new SimpleObjectProperty<>();
    private ObjectProperty<EventHandler<MouseEvent>>    onMouseDoubleClickedProperty    = new SimpleObjectProperty<>();

    // CONSTRUCTORS
    public ButtonWithDblClick() {
        super();
        addClickedEventHandler();
    }

    public ButtonWithDblClick(String text) {
        super(text);
        addClickedEventHandler();
    }

    public ButtonWithDblClick(String text, Node graphic) {
        super(text, graphic);
        addClickedEventHandler();
    }

    private class ClickRunner implements Runnable {

        private final Runnable  onClick;
        private boolean         aborted = false;

        public ClickRunner(Runnable onClick) {
            this.onClick = onClick;
        }

        public void abort() {
            this.aborted = true;
        }

        @Override
        public void run() {
            try {
                Thread.sleep(singleClickDelayMillis);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            if (!aborted) {
                Platform.runLater(onClick::run);
            }
        }
    }

    private void addClickedEventHandler() {
        //Handling the mouse clicked event (not using 'onMouseClicked' so it can still be used by developer).
        EventHandler<MouseEvent> eventHandler = me -> {
            switch (me.getButton()) {
                case PRIMARY:
                    if (me.getClickCount() == 1) {
                        latestClickRunner = new ClickRunner(() -> {
                            System.out.println("ButtonWithDblClick : SINGLE Click fired");
                            onMouseSingleClickedProperty.get().handle(me);
                        });
                        CompletableFuture.runAsync(latestClickRunner);
                    }
                    if (me.getClickCount() == 2) {
                        if (latestClickRunner != null) {
                            latestClickRunner.abort();
                        }
                        System.out.println("ButtonWithDblClick : DOUBLE Click fired");
                        onMouseDoubleClickedProperty.get().handle(me);
                    }
                    break;
                case SECONDARY:
                    // Right-click operation. Not implemented since usually no double RIGHT click needs to be caught.
                    break;
                default:
                    break;
            }
        };
        //Adding the event handler
        addEventHandler(MouseEvent.MOUSE_CLICKED, eventHandler);
    }

    public void setOnMouseSingleClicked(EventHandler<MouseEvent> eventHandler) {
        this.onMouseSingleClickedProperty.set(eventHandler);
    }

    public void setOnMouseDoubleClicked(EventHandler<MouseEvent> eventHandler) {
        this.onMouseDoubleClickedProperty.set(eventHandler);
    }
    public long getSingleClickDelayMillis() {
        return singleClickDelayMillis;
    }

    public void setSingleClickDelayMillis(long singleClickDelayMillis) {
        this.singleClickDelayMillis = singleClickDelayMillis;
    }

}

public void start(Stage stage) {
    VBox root = new VBox();

    Label lbl = new Label("Double click me");
    lbl.setOnMouseClicked(mouseEvent -> {
        // CLICK catches
        if (mouseEvent.getClickCount() == 2) {
            System.out.println("Label double clicked");
        } else if (mouseEvent.getClickCount() == 1)
            System.out.println("Label clicked");
    });

    Button btn = new Button("Double click me too");
    btn.setOnMousePressed(mouseEvent -> {
        // CLICK catches
        if (mouseEvent.getClickCount() == 1) {
            System.out.println("Button clicked");
        } else if (mouseEvent.getClickCount() == 2)
            System.out.println("Button double clicked");
    });

    ButtonWithDblClick btn2 = new ButtonWithDblClick("Double click me three ;-)");
    btn2.setOnMouseSingleClicked(me -> {
        System.out.println("BUTTON_2 : Fire SINGLE Click");
    });
    btn2.setOnMouseDoubleClicked(me -> {
        System.out.println("BUTTON_2 : Fire DOUBLE Click");
    });

    root.getChildren().add(lbl);
    root.getChildren().add(btn);
    root.getChildren().add(btn2);

    Scene scene = new Scene(root);
    stage.setScene(scene);
    stage.show();
}

public static void main(String[] args) {
    launch();
}

}

于 2021-12-27T08:50:02.177 に答える
0

押されたマウス ボタンの数 (==2) をテストする場合は、サブメソッドでコーディングしないでください。次は働いています:

listView.setOnMouseClicked(new EventHandler<MouseEvent>() {
            @Override
            public void handle(MouseEvent mouseEvent) {
                if( mouseEvent.getButton().equals(MouseButton.SECONDARY)) {
                    System.out.println("isSecondaryButtonDown");
                    mouseEvent.consume();
                    // ....
                }
                else
               if(mouseEvent.getButton().equals(MouseButton.PRIMARY)){
                    if(mouseEvent.getClickCount() == 2){
                        System.out.println("Double clicked");
                       // mousePressedInListViewDC(mouseEvent);
                    }
                    else
                    if(mouseEvent.getClickCount() == 1){
                        System.out.println("1 clicked");
                        mousePressedInListView1C(mouseEvent);
                    }
               }
            }
        })

;

于 2021-09-04T09:46:30.340 に答える