JavaFx TreeCell how to expand nodes after one second

419 views Asked by At

i'm implementing the Drag&Drop on a generic TreeView. My purpose is to expand a folder during DragEntered event after a second of stationing, actual code:

setOnDragEntered(e -> {
    TreeItem<TreeItemContent> enteredItem = getSourceItem(e);
    if(model.isFolder(enteredItem)){
       enteredItem.setGraphic(images.getFolderOpened());
       enteredItem.setExpanded(true);
    }
    e.consume();
});

desired:

setOnDragEntered(e -> {
    TreeItem<TreeItemContent> enteredItem = getSourceItem(e);
    if(model.isFolder(enteredItem)){
       if(dragDuration >= 1 sec){
          enteredItem.setGraphic(images.getFolderOpened());
          enteredItem.setExpanded(true);
       }
    }
    e.consume();
});

There is a standard resolution for this scope ? or i must implement this function by myself ?

2

There are 2 answers

1
ItachiUchiha On BEST ANSWER

You can use a PauseTransition for adding the delay. On its setOnFinished(), you can add an action to be performed after the supplied time has elapsed.

On setOnDragEntered(), you can start the PauseTransition and on setOnDragExited(), check the status of PauseTransition and if it is still in RUNNING status, stop it.

Here is a simple code, which uses, setOnMouseEntered() and setOnMouseExited(), instead of the above two mentioned events, on a Button. But, this should be more than enough to give you an idea.

Code :

import javafx.animation.Animation;
import javafx.animation.PauseTransition;
import javafx.application.Application;
import javafx.event.ActionEvent;
import javafx.geometry.Pos;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.Label;
import javafx.scene.layout.VBox;
import javafx.stage.Stage;
import javafx.util.Duration;

public class Main extends Application {

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

    @Override
    public void start(Stage primaryStage) throws Exception {
        Label label = new Label("Hi");

        Button button = new Button("Add");
        PauseTransition pt = new PauseTransition(Duration.millis(1000));

        pt.setOnFinished( ( ActionEvent event ) -> {
            label.setText(String.valueOf("Done!"));
        });

        button.setOnMouseEntered(event -> {
            pt.play();
        });

        button.setOnMouseExited(event -> {
            if(pt.getStatus() == Animation.Status.RUNNING) {
                pt.stop();
                label.setText("Interrupted");
            }
        });

        VBox box = new VBox(20, label, button);
        box.setAlignment(Pos.CENTER);

        Scene scene = new Scene(box, 200, 200);
        primaryStage.setTitle("Welcome");
        primaryStage.setScene(scene);
        primaryStage.show();
    }
}
0
Alessandro On

I haven't found a standard solution for this issue, but i have resolved with a custom implementation:

setOnDragEntered(e -> {
    TreeItem<TreeItemContent> enteredItem = getSourceItem(e);
    model.setEnteredItem(enteredItem);
    if(model.isFolder(enteredItem)){
       new Thread(()->{
            try {
                Thread.sleep(1000);
                if(enteredItem == model.getEnteredItem()){
                    enteredItem.setGraphic(images.getFolderOpened());
                    enteredItem.setExpanded(true);
                }
            } catch (Exception e1) {}
       }).start();
    }
}

In this way i can compare the first enteredItem with the enteredItem that i have after a second.

For completeness:

private TreeItem<TreeItemContent> getSourceItem(InputEvent e){
   return ((TreeCell)e.getSource()).getTreeItem();
}