JavaFX Drop Plain Text Files

JavaFX drag and drop is easy. Modern apps require the ability to drop files when filling content, instead of opening the files in another application, copying the contents to the clipboard and then pasting the clipboard contents into the new app. Make sure to include drop capabilities in your JavaFX apps. It’s a good idea to have fully flushed out drop events included in your JavaFX applications from the start, or you’re likely to lose customers.

This tutorial shows how to include the ability to drag plain text files on to a JavaFX text area and have that JavaFX text area auto-populate with the contents of the files. Plain text files may or may not have the extension of *.txt. Plain text files  are not the same as rich text files that almost always have the extension of *.rtf.

Note: If you want to see details on dropping images onto a JavaFX ImageView, check out “JavaFX Drag and Drop Images.”

Capturing the correct drag event is the key to capturing dropped file content in JavaFX TextAreas.

Here’s the controller code.

package com.whatisjavafx;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.net.URL;
import java.util.List;
import java.util.ResourceBundle;

import javafx.fxml.FXML;
import javafx.scene.control.TextArea;
import javafx.scene.input.DragEvent;
import javafx.scene.input.Dragboard;
import javafx.scene.input.TransferMode;

public class TextViewController {

    @FXML
    private ResourceBundle resources;

    @FXML
    private URL location;

    @FXML // fx:id="myTextArea"
    private TextArea myTextArea;

    @FXML
    void draggingOver(DragEvent event) {
      Dragboard board = event.getDragboard();
      if (board.hasFiles()) {
        event.acceptTransferModes(TransferMode.ANY);
      }
      
    }

    @FXML
    void dropping(DragEvent event) {
      try {
        Dragboard board = event.getDragboard();
        List<File> phil = board.getFiles();
        FileInputStream fis;
        fis = new FileInputStream(phil.get(0));
      
        StringBuilder builder = new StringBuilder();
        int ch;
        while((ch = fis.read()) != -1){
            builder.append((char)ch);
        }
        
        fis.close();
        
        myTextArea.setText(builder.toString());

      } catch (FileNotFoundException fnfe) {
        fnfe.printStackTrace();
      } catch (IOException ioe) {
        ioe.printStackTrace();
      }
     }

    @FXML
    void initialize() {}
}

 

In Scene Builder, we have already defined methods to handle On Drag Dropped and On Drag Over. The One Drag Over method is dragging Over() and the On Drag Dropped method is dropping(). These are now implemented in the Controller with the @FXML annotation to make sure they are linked.

The draggingOver() method checks to see if a file is being dragged over, and accepts that as a valid drag. Dragging something other than a file, does not result in the cursor change that lets the user know a potentially valid drop is happening.

The dropping() method is primarily concerned grabbing the contents of the file, and placing it in the TextArea. If there are multiple files being dragged, it only grabs the first one. You can grab the rest of the files in other types of apps, but this simple app only displays one file, so only needs the first index of the List<File>.

FileNotFoundException and IOExceptions are caught, because we are dealing with Java IO and files. We also close the file input stream, even though that is not strictly required in newer Java applications.

The rest of the behavior is just using a StringBuilder to capture the plain text from the file via a FileInputStream. Remember that if there are any hidden characters, they can cause odd looking results in the text area.

That’s really all there is dragging plain text files into JavaFX applications. Obviously, this being a JavaFX applications, the JavaFX application also has an FXML file and an Application class.

Here’s the FXML code. To see it in a pretty form, just open it with a modern copy of Scene Builder. Remember that the controller needs to be defined with a fully qualified class name. That means the JavaFX controller’s package must be used with the class name.

<?xml version="1.0" encoding="UTF-8"?>

<?import javafx.scene.control.TextArea?>
<?import javafx.scene.layout.VBox?>


<VBox 
xmlns:fx="http://javafx.com/fxml/1" 
xmlns="http://javafx.com/javafx/8.0.65" 
fx:controller="com.whatisjavafx.TextViewController">
   <children>
      <TextArea 
      fx:id="myTextArea" 
      onDragDropped="#dropping" 
      onDragOver="#draggingOver" 
      prefHeight="365.0" 
      prefWidth="536.0" />
   </children>
</VBox>

 

For this example, we just used a VBox and put a TextArea in it. No other children. The FXML is pretty straight forward, so might not even want to bother opening it up in Scene Builder.

Here’s the Main class for completeness. Nothing fancy happening here. JavaFX requires an implementation of Application. We also load the FXML file using an FXMLLoader. That FXMLLoader in turn handles the loading injection of the @FXML into the controller.

The full scene graph consists of a Stage containing a Scene that contains a VBox that contains a TextArea.

package com.whatisjavafx;
  
import java.net.URL;

import javafx.application.Application;
import javafx.fxml.FXMLLoader;
import javafx.scene.Scene;
import javafx.scene.layout.VBox;
import javafx.stage.Stage;


public class Main extends Application {
  @Override
  public void start(Stage stage) {
    try {
      URL url = 
          getClass()
          .getResource("FxmlTextView.fxml");
      VBox root = FXMLLoader.load(url);

      Scene scene = new Scene(root);
      stage.setScene(scene);
      stage
      .setTitle("Drop Text");
      stage.show();
    } catch(Exception e) {
      e.printStackTrace();
    }
  }
  
  public static void main(String[] args) {
    launch(args);
  }
}

 

Drag and drop in JavaFX is not so bad, really. To see the complete list of drop tutorials, checkout the Dragboard tutorials page. Remember to keep checking back for more tutorials as they are added.

Leave a Reply

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