Search code examples
javafxnodesexpandtreecell

JavaFx TreeCell how to expand nodes after one second


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 ?


Solution

  • 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();
        }
    }