Search code examples
javalistviewjavafxdrag-and-dropdrag

JavaFX Drag and Drop on ListView from Explorer


Im trying to implement the ability to add paths of folders in my program by simply dragging the folder from the explorer to my ListView.

The ListView is type String:

In the controller class:

    public class Controller {
  @FXML
        protected ListView<String> folderList;
        protected void init(){
        
                folderList.setOnDragOver(new EventHandler<DragEvent>() {
        
                    @Override
                    public void handle(DragEvent event) {
                        System.out.println("test");
        
                        if (event.getGestureSource() != folderList) {
                            event.acceptTransferModes(TransferMode.ANY);
                        }
                        event.consume();
                    }
                });
                
                folderList.setOnDragDropped(new EventHandler<DragEvent>() {
        
                    @Override
                    public void handle(DragEvent event) {
                        Dragboard db = event.getDragboard();
                        boolean succ = false;
                        System.out.println(db);
        
                        try {
                            doFolderAdd(new Folder(db.getString()));
                            succ = true;
                        } catch (IOException e) {
                            e.printStackTrace();
                        }
        
                        event.setDropCompleted(succ);
                        event.consume();
                    }
                });
        }
    }

My main class:

public class Main extends Application {

    @Override
    public void start(Stage primaryStage) throws IOException, InterruptedException, WriterException {


        FXMLLoader loader = new FXMLLoader(getClass().getResource("/ch/makery/address/view/App.fxml"));

        Parent root = (Parent) loader.load();

        ctrl = loader.getController();
        ctrl.init();
        Scene scene = new Scene(root, 600, 400);
        primaryStage.setTitle("test");
        primaryStage.setScene(scene);
        ctrl.setStage(primaryStage);
        primaryStage.show();

    }



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

Corresponding FXML:

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

<?import javafx.scene.text.*?>
<?import javafx.scene.control.*?>
<?import java.lang.*?>
<?import javafx.scene.layout.*?>
<?import javafx.scene.layout.AnchorPane?>

<Pane maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" onDragOver="" prefHeight="400.0" prefWidth="600.0" style="-fx-background-color: #4c4c4c;" xmlns="http://javafx.com/javafx/8" xmlns:fx="http://javafx.com/fxml/1" fx:controller="ch.makery.address.model.Controller">
    <children>
      <ListView id="testList" fx:id="list" layoutX="55.0" layoutY="58.0" prefHeight="200.0" prefWidth="200.0" />
    </children>
</Pane>

I cannot even test if my logic of adding paths is working, since none of these Events are ever fired when I drag an item from a windows explorer window onto the list.

What I noticed is, that if I open a FileChooser from my program, and drag an item from there onto the list, the event is indeed fired, however that is the only case. I was not able to find anything about this issue.

On drag, from a explorer window, it only shows me the 'denied/blocked' icon


Solution

  • You mention the following:

    • The problem only occurs when launching the JavaFX application from Eclipse.
    • You're running Eclipse with administrator privileges.
    • You can drag things from Eclipse to the JavaFX application.

    With that information, you're most likely running into the issue described over at Why doesn't usual Drag&Drop work in Windows 10? on Super User. Here's an excerpt from the accepted answer:

    You see a effect of the User Account Control. Drag & Drop only works for programs that have the same permission level. If you run an application as admin, you can only drag and drop files from applications that also run as admin.

    User Interface Privilege Isolation (UIPI)

    UIPI blocks Windows messages being sent from process with a lower MIC level to one running at a higher MIC level. Drag-and-drop is implemented via Windows messages. Therefore, if you try and drag-and-drop a file from Windows Explorer (medium MIC) to Notepad running elevated (high MIC), the Windows messages are blocked and drag-and-drop doesn’t work.

    Since Eclipse has administrator privileges so does your JavaFX application. File Explorer does not run with administrator privileges, at least not by default, hence your issue. The solution is to either make File Explorer run with administrator privileges, don't run Eclipse with said privileges, or to simply "suffer through" this problem during development (or find a way to make sure the JavaFX application doesn't inherit the admin status).