Ernest Duodu

Ernest is a developer at IDRSolutions. He focuses mainly on our JavaFX PDF Viewer implementation. He was a speaker at JavaOne 2014, where he did a joint session titled “Lessons learnt developing a NetBeans PDF viewer plugin in JavaFX”. Aside programming, he also enjoys a wide variety of hobbies which includes sky-diving, photography, exercising and listening to music.

How to implement Drag and Drop Function in a JavaFX Application

3 min read

I have spent alot of time working on implementing more functionality of our JavaFX PDF Viewer. I recently added a drag and drop functionality to the viewer which enables the user to drag and drop a PDF file into the viewer to be decoded and displayed. This is very easy to implement in JavaFX so here is a short tutorial for you to follow.

In this article, we will create a simple scene, and add the DnD function which will only accept image files (jpeg, jpg ,png) . This file will them be displayed when dropped unto the application.

Drag and drop support requires several items.

1. Component that will accept the draggable objects.

In this example we will use a StackPane to accept the DnD function. Once the image has been dropped onto the StackPane the we will use an ImageView to display the image

The code for displaying the image will be

Image img = new Image("path_to_image");
 
ImageView imageView = new ImageView();
 
imageView.setImage(img);

 

2. Handling the DnD Events

There are different DnD events we can add to the StackPane. In this example we will add three events to the StackPane.

The first we will add is the setOnDragOver

stackPane.setOnDragOver(new EventHandler() {
            @Override
            public void handle(final DragEvent event) {
               //Do something when an Object is dragged over the StackPane
            }
        });

We will add an event which will detect when a an object is dropped onto the StackPane. This will be the setOnDragDropped

contentPane.setOnDragDropped(new EventHandler() {
            @Override
            public void handle(final DragEvent event) {
                //Do something when an object is dropped onto the StackPane
            }
        });

The last we will add is the setOnDragExited

contentPane.setOnDragExited(new EventHandler() {
            @Override
            public void handle(final DragEvent event) {
               //Do something when an object exits the StackPane
            }
        });

3. Filter to control which types of file are supported

Since we only want our program to accept only images, we will want to accept specific file types (i.e. png, jpeg). In this case, when an object is dragged over the StackPane we will check if it is an image file, if not,we tell our program not to accept it. We will store any item which is being dragged to the StackPane in a DragBoard, we will then check if the object stored in the DragBoard is an image file type.

 final Dragboard db = e.getDragboard();
 
        final boolean isAccepted = db.getFiles().get(0).getName().toLowerCase().endsWith(".png")
                || db.getFiles().get(0).getName().toLowerCase().endsWith(".jpeg")
                || db.getFiles().get(0).getName().toLowerCase().endsWith(".jpg");
 
        if (db.hasFiles() && isAccepted) {
           //display the image file
        } else {
            e.consume();
        }

Now we put this all together in a code example

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.util.logging.Level;
import java.util.logging.Logger;
import javafx.application.Application;
import static javafx.application.Application.launch;
import javafx.application.Platform;
import javafx.event.EventHandler;
import javafx.scene.Scene;
import javafx.scene.image.Image;
import javafx.scene.image.ImageView;
import javafx.scene.input.DragEvent;
import javafx.scene.input.Dragboard;
import javafx.scene.input.TransferMode;
import javafx.scene.layout.BorderPane;
import javafx.scene.layout.StackPane;
import javafx.scene.paint.Color;
import javafx.stage.Stage;
 
public class DragAndDropExample extends Application {
 
 
    ImageView imageView;
    StackPane contentPane;
    BorderPane layout;
 
    public static void main(String[] args) {
        launch(args);
    }
 
    @Override
    public void start(Stage primaryStage) {
        primaryStage.setTitle("Drag and Drop");
        layout = new BorderPane();
        contentPane = new StackPane();
        Scene scene = new Scene(layout, 800, 800, Color.WHITE);
 
 
 
 
 
        contentPane.setOnDragOver(new EventHandler() {
            @Override
            public void handle(final DragEvent event) {
                mouseDragOver(event);
            }
        });
 
        contentPane.setOnDragDropped(new EventHandler() {
            @Override
            public void handle(final DragEvent event) {
                mouseDragDropped(event);
            }
        });
 
         contentPane.setOnDragExited(new EventHandler() {
            @Override
            public void handle(final DragEvent event) {
                contentPane.setStyle("-fx-border-color: #C6C6C6;");
            }
        });
 
       layout.setCenter(contentPane);
 
        primaryStage.setScene(scene);
        primaryStage.show();
 
    }
 
    void addImage(Image i, StackPane pane){
 
        imageView = new ImageView();
        imageView.setImage(i);
        pane.getChildren().add(imageView);
    }
 
  private void mouseDragDropped(final DragEvent e) {
        final Dragboard db = e.getDragboard();
        boolean success = false;
        if (db.hasFiles()) {
            success = true;
            // Only get the first file from the list
            final File file = db.getFiles().get(0);
            Platform.runLater(new Runnable() {
                @Override
                public void run() {
                    System.out.println(file.getAbsolutePath());
                    try {
                        if(!contentPane.getChildren().isEmpty()){
                            contentPane.getChildren().remove(0);
                        }
                        Image img = new Image(new FileInputStream(file.getAbsolutePath()));  
 
                        addImage(img, contentPane);
                    } catch (FileNotFoundException ex) {
                        Logger.getLogger(DragAndDropExample.class.getName()).log(Level.SEVERE, null, ex);
                    }
                }
            });
        }
        e.setDropCompleted(success);
        e.consume();
    }
 
    private  void mouseDragOver(final DragEvent e) {
        final Dragboard db = e.getDragboard();
 
        final boolean isAccepted = db.getFiles().get(0).getName().toLowerCase().endsWith(".png")
                || db.getFiles().get(0).getName().toLowerCase().endsWith(".jpeg")
                || db.getFiles().get(0).getName().toLowerCase().endsWith(".jpg");
 
        if (db.hasFiles()) {
            if (isAccepted) {
                contentPane.setStyle("-fx-border-color: red;"
              + "-fx-border-width: 5;"
              + "-fx-background-color: #C6C6C6;"
              + "-fx-border-style: solid;");
                e.acceptTransferModes(TransferMode.COPY);
            }
        } else {
            e.consume();
        }
    }
 
}

Now lets run the Application.

This image shows when we drag a non image file to the application


Screen Shot 2015-04-29 at 23.29.38

This image shows when we drag an image file to the application


Screen Shot 2015-04-29 at 23.27.39

This image shows when we drop the image file unto the application


Screen Shot 2015-04-29 at 23.27.14

Hopefully you have found this quick guide useful.

If you’re a first-time reader, or simply want to be notified when we post new articles and updates, you can keep up to date by social media (Twitter, Facebook and Google+) or the Blog RSS.

Ernest Duodu

Ernest is a developer at IDRSolutions. He focuses mainly on our JavaFX PDF Viewer implementation. He was a speaker at JavaOne 2014, where he did a joint session titled “Lessons learnt developing a NetBeans PDF viewer plugin in JavaFX”. Aside programming, he also enjoys a wide variety of hobbies which includes sky-diving, photography, exercising and listening to music.

5 Replies to “How to implement Drag and Drop Function in a…”

  1. Hi there Ernest.

    Thanks for creating this tutorial! I was wondering, can’t you migrate to Java 8?. JavaFX8 with lambdas are a god send for event handling. Also for tutorials like this one. Methinks that for desktop applications like the PDF Reader you’re doing, there’s more agency to use the prefered JVM version, right?

    1. Yes you’re definitely right Loïc. Lambda’s are really great for event handling. Make you write clean and short readable code. I did not use them specifically because not everyone reading this article might have migrated to Java8 yet. You can also check my article on Lambda Expression

  2. Good post, but the drag event handlers should rather be in the form:

    contentPane.setOnDragX(new EventHandler() {
    @Override
    public void handle(final DragEvent event) {
    //call to method to handle mouseDragX event or codes to handle event
    }
    });

Leave a Reply

Your email address will not be published. Required fields are marked *