web-dev-qa-db-fra.com

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 un événement différent entre un clic et un double clic.

Merci

53
Delkaspo

Oui, vous pouvez détecter des clics simples, doubles voire multiples:

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 (commun) de la souris déclenche l'événement. Lisez l'api de getClickCount() pour conclure qu'il peut y avoir plusieurs clics autres que simples ou doubles. Cependant, j'ai du mal à distinguer les événements de simple et double clic. Parce que le nombre de premiers clics du double clic augmentera également un seul événement.

87
Uluk Biy

Voici un autre morceau de code qui peut être utilisé si vous devez faire la distinction entre un simple et un double-clic et devez prendre une action spécifique dans les deux 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.");
    }
}
7
mipa

La réponse de P. Pandey est l'approche la plus simple qui fait la distinction entre le simple et le double clic, mais cela 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
parityerror

Voici comment j'ai implémenté le double clic

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
P. Pandey

Adhérer à Java SE 8 expressions lambda ressemblerait à 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 l'instanciation de classe d'origine et la méthode prioritaire (x). -À mon avis-

1

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

En un seul clic, nous encapsulons l'opération en un seul clic dans un exécutable abortable. Cette exécutable attend un certain temps (c'est-à-dire SINGLE_CLICK_DELAY) avant d'être exécuté.

En attendant, si un deuxième clic, c'est-à-dire un double-clic, se produit, l'opération de simple clic est abandonnée et seule l'opération de double-clic est effectuée.

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


Voici le code complet. Pour l'utiliser, seules les trois lignes TODO doivent être remplacées par les gestionnaires voulus.

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;
        }
    });
}
1
Markus Weninger