Friday, August 19, 2016

How to implement Drag and Drop Function in a JavaFX Application

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
  1. Image img = new Image("path_to_image");
  2. ImageView imageView = new ImageView();
  3. 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
  1. stackPane.setOnDragOver(new EventHandler() {
  2.             @Override
  3.             public void handle(final DragEvent event) {
  4.                //Do something when an Object is dragged over the StackPane
  5.             }
  6.         });
We will add an event which will detect when a an object is dropped onto the StackPane. This will be the setOnDragDropped
  1. contentPane.setOnDragDropped(new EventHandler() {
  2.             @Override
  3.             public void handle(final DragEvent event) {
  4.                 //Do something when an object is dropped onto the StackPane
  5.             }
  6.         });
The last we will add is the setOnDragExited
  1. contentPane.setOnDragExited(new EventHandler() {
  2.             @Override
  3.             public void handle(final DragEvent event) {
  4.                //Do something when an object exits the StackPane
  5.             }
  6.         });
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.
  1.  final Dragboard db = e.getDragboard();
  2.  
  3.         final boolean isAccepted = db.getFiles().get(0).getName().toLowerCase().endsWith(".png")
  4.                 || db.getFiles().get(0).getName().toLowerCase().endsWith(".jpeg")
  5.                 || db.getFiles().get(0).getName().toLowerCase().endsWith(".jpg");
  6.  
  7.         if (db.hasFiles() && isAccepted) {
  8.            //display the image file
  9.         } else {
  10.             e.consume();
  11.         }
Now we put this all together in a code example
  1. import java.io.File;
  2. import java.io.FileInputStream;
  3. import java.io.FileNotFoundException;
  4. import java.util.logging.Level;
  5. import java.util.logging.Logger;
  6. import javafx.application.Application;
  7. import static javafx.application.Application.launch;
  8. import javafx.application.Platform;
  9. import javafx.event.EventHandler;
  10. import javafx.scene.Scene;
  11. import javafx.scene.image.Image;
  12. import javafx.scene.image.ImageView;
  13. import javafx.scene.input.DragEvent;
  14. import javafx.scene.input.Dragboard;
  15. import javafx.scene.input.TransferMode;
  16. import javafx.scene.layout.BorderPane;
  17. import javafx.scene.layout.StackPane;
  18. import javafx.scene.paint.Color;
  19. import javafx.stage.Stage;
  20.  
  21. public class DragAndDropExample extends Application {
  22.  
  23.     ImageView imageView;
  24.     StackPane contentPane;
  25.     BorderPane layout; 
  26.     public static void main(String[] args) {
  27.         launch(args);
  28.     } 
  29.     @Override
  30.     public void start(Stage primaryStage) {
  31.         primaryStage.setTitle("Drag and Drop");
  32.         layout = new BorderPane();
  33.         contentPane = new StackPane();
  34.         Scene scene = new Scene(layout, 800, 800, Color.WHITE);
  35.  
  36.         contentPane.setOnDragOver(new EventHandler() {
  37.             @Override
  38.             public void handle(final DragEvent event) {
  39.                 mouseDragOver(event);
  40.             }
  41.         }); 
  42.         contentPane.setOnDragDropped(new EventHandler() {
  43.             @Override
  44.             public void handle(final DragEvent event) {
  45.                 mouseDragDropped(event);
  46.             }
  47.         }); 
  48.          contentPane.setOnDragExited(new EventHandler() {
  49.             @Override
  50.             public void handle(final DragEvent event) {
  51.                 contentPane.setStyle("-fx-border-color: #C6C6C6;");
  52.             }
  53.         });
  54.        layout.setCenter(contentPane);
  55.         primaryStage.setScene(scene);
  56.         primaryStage.show();
  57.     }
  58.     void addImage(Image i, StackPane pane){
  59.         imageView = new ImageView();
  60.         imageView.setImage(i);
  61.         pane.getChildren().add(imageView);
  62.     }
  63.   private void mouseDragDropped(final DragEvent e) {
  64.         final Dragboard db = e.getDragboard();
  65.         boolean success = false;
  66.         if (db.hasFiles()) {
  67.             success = true;
  68.             // Only get the first file from the list
  69.             final File file = db.getFiles().get(0);
  70.             Platform.runLater(new Runnable() {
  71.                 @Override
  72.                 public void run() {
  73.                     System.out.println(file.getAbsolutePath());
  74.                     try {
  75.                         if(!contentPane.getChildren().isEmpty()){
  76.                             contentPane.getChildren().remove(0);
  77.                         }
  78.                         Image img = new Image(new FileInputStream(file.getAbsolutePath()));  
  79.  
  80.                         addImage(img, contentPane);
  81.                     } catch (FileNotFoundException ex) {
  82.                         Logger.getLogger(DragAndDropExample.class.getName()).log(Level.SEVERE, null, ex);
  83.                     }
  84.                 }
  85.             });
  86.         }
  87.         e.setDropCompleted(success);
  88.         e.consume();
  89.     }
  90.     private  void mouseDragOver(final DragEvent e) {
  91.         final Dragboard db = e.getDragboard();
  92.  
  93.         final boolean isAccepted = db.getFiles().get(0).getName().toLowerCase().endsWith(".png")
  94.                 || db.getFiles().get(0).getName().toLowerCase().endsWith(".jpeg")
  95.                 || db.getFiles().get(0).getName().toLowerCase().endsWith(".jpg");
  96.  
  97.         if (db.hasFiles()) {
  98.             if (isAccepted) {
  99.                 contentPane.setStyle("-fx-border-color: red;"
  100.               + "-fx-border-width: 5;"
  101.               + "-fx-background-color: #C6C6C6;"
  102.               + "-fx-border-style: solid;");
  103.                 e.acceptTransferModes(TransferMode.COPY);
  104.             }
  105.         } else {
  106.             e.consume();
  107.         }
  108.     }
  109. }
Now lets run the Application.


Hopefully you have found this quick guide useful.
Written by Ernest Duodu

If you found this post interesting, follow and support us.
Suggest for you:

The Complete Java Developer Course

Java Programming For Beginners

Complete Java For Selenium WebDriver And Test Automation

The Complete Android & Java Course - Build 21 Android Apps


Basic guide for Class Objects and Methods in Java for Selenium Webdriver

No comments:

Post a Comment