Javafx 2 Cliquez et double cliquez

je voudrais savoir s'il était possible de détecter le double-clic dans JavaFX 2 ? et comment ?

je voudrais faire événement différent entre un clic et double-cliquez.

Merci

43
demandé sur Delkaspo 2012-06-08 17:07:15

6 réponses

Oui, vous pouvez détecter simple, double voire plusieurs clics:

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 est utilisé pour déterminer si le bouton gauche de la souris (communément) déclenche l'événement. Lire l'api de getClickCount() pour conclure qu'il y a peut-être des comptes de clics multiples autres que simple ou double. Cependant je trouve qu'il est difficile de faire la distinction entre les événements de simple et double clic. Parce que le premier compte de clic du double claquement va monter un événement simple aussi bien.

77
répondu Uluk Biy 2012-06-08 14:30:33

voici un autre morceau de code qui peut être utilisé si vous devez faire une distinction entre un simple - et un double-clic et avoir à prendre une action spécifique dans l'un ou l'autre cas.

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.");
    }
}
6
répondu mipa 2016-03-27 09:26:31

la réponse de P. Pandey est l'approche la plus simple qui distingue en fait entre simple et double clic, mais elle n'a pas fonctionné pour moi. D'une part, la fonction "currentTimeMillis" renvoie déjà des millisecondes, donc la diviser par 1000 ne semble pas nécessaire. La version ci-dessous a fonctionné pour moi d'une manière plus cohérente.

 @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...   
}
3
répondu parityerror 2016-07-18 03:18:40

Voici comment j'ai implémenté double click

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

}

2
répondu P. Pandey 2016-02-12 12:03:38

adhérant à Java SE 8 Les expressions lambda ressembleraient à quelque chose comme ceci:

node.setOnMouseClicked(event -> {
    if(event.getButton().equals(MouseButton.PRIMARY) && event.getClickCount() == 2) {
        handleSomeAction();
    }
});

Une fois que vous vous êtes habitué aux expressions lambda - elles finissent par être plus compréhensibles que la méthode originale d'instanciation de classe et de dépassement (x). -À mon avis-

0
répondu Joseph Malachosky 2018-03-08 21:14:50

Puisqu'il n'est pas possible de faire la distinction par défaut entre un simple clic et un double clic, nous utilisons l'approche suivante:

en simple clic, nous enveloppons l'opération en simple clic dans un runnable avortable. Cette exécutable attend un certain temps (i.e.,SINGLE_CLICK_DELAY) avant d'être exécuté.

en attendant, si un second clic, c'est-à-dire un double clic, se produit, l'opération de simple clic est annulée et seule l'opération de double clic est effectuer.

de cette façon, soit le simple clic ou l'opération de double-clic est effectuée, mais jamais les deux.


voici le code complet. Pour l'utiliser, seuls les trois TODO les lignes doivent être remplacés par les gestionnaires.

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;
        }
    });
}
0
répondu Markus Weninger 2018-03-21 09:38:45