I've been wondering how you would be able to drag and drop list view items between 2 java fx windows.
The code that I used was
tilePane.setOnDragDropped((event) -> {
Dragboard db = event.getDragboard();
boolean success = false;
if (db.hasString()) {
TilePane pane = (TilePane) event.getGestureTarget();
if (pane.getChildren().size() >= 10) {
//error
} else {
ListView<Item> list = (ListView<Item>) event
.getGestureSource();
addShopItem(pane, list.getSelectionModel()
.getSelectedItem());
success = true;
}
}
event.setDropCompleted(success);
event.consume();
});
Both the list view and tile pane used to be in one window but I've decided to make seperate them into different javafx windows so it would allow for more flexibility. One window has the list view and the other has the tilepane.
I would like to drag the list view item to the tilepane(other window) but this code no longer works because getGestureTarget() is null for different applications.
Thanks
It does look like the gesture source and target both get set to null when the drag leaves the JavaFX application (e.g. moving it between two windows).
For the gesture source, you may need to manage that yourself by creating a property and setting its value in the onDragDetected
handler.
The gesture target is surely just the tile pane to which you attached the onDragDropped
listener. So I don't see that you need to access that from the event; though you could use the same technique.
Example:
import javafx.application.Application;
import javafx.beans.property.ObjectProperty;
import javafx.beans.property.SimpleObjectProperty;
import javafx.scene.Scene;
import javafx.scene.control.ListCell;
import javafx.scene.control.ListView;
import javafx.scene.input.ClipboardContent;
import javafx.scene.input.Dragboard;
import javafx.scene.input.TransferMode;
import javafx.scene.layout.BorderPane;
import javafx.stage.Stage;
public class DnDListViews extends Application {
private int counter = 0 ;
private final ObjectProperty<ListCell<String>> dragSource = new SimpleObjectProperty<>();
@Override
public void start(Stage primaryStage) {
populateStage(primaryStage);
primaryStage.show();
Stage anotherStage = new Stage();
populateStage(anotherStage);
anotherStage.setX(primaryStage.getX() + 300);
anotherStage.show();
}
private void populateStage(Stage stage) {
ListView<String> listView = new ListView<>();
for (int i=0; i<5; i++ ) {
listView.getItems().add("Item "+(++counter));
}
listView.setCellFactory(lv -> {
ListCell<String> cell = new ListCell<String>(){
@Override
public void updateItem(String item , boolean empty) {
super.updateItem(item, empty);
setText(item);
}
};
cell.setOnDragDetected(event -> {
if (! cell.isEmpty()) {
Dragboard db = cell.startDragAndDrop(TransferMode.MOVE);
ClipboardContent cc = new ClipboardContent();
cc.putString(cell.getItem());
db.setContent(cc);
dragSource.set(cell);
}
});
cell.setOnDragOver(event -> {
Dragboard db = event.getDragboard();
if (db.hasString()) {
event.acceptTransferModes(TransferMode.MOVE);
}
});
cell.setOnDragDone(event -> listView.getItems().remove(cell.getItem()));
cell.setOnDragDropped(event -> {
Dragboard db = event.getDragboard();
if (db.hasString() && dragSource.get() != null) {
// in this example you could just do
// listView.getItems().add(db.getString());
// but more generally:
ListCell<String> dragSourceCell = dragSource.get();
listView.getItems().add(dragSourceCell.getItem());
event.setDropCompleted(true);
dragSource.set(null);
} else {
event.setDropCompleted(false);
}
});
return cell ;
});
BorderPane root = new BorderPane(listView);
Scene scene = new Scene(root, 250, 450);
stage.setScene(scene);
}
public static void main(String[] args) {
launch(args);
}
}
If the dragboard supported attaching arbitrary object references for drag and drop within the same JVM (see JIRA request, and vote if so inclined) then this would be quite a bit easier...
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With