I would like to drag and drop an item from a treeview into a textArea.
The goal is to write in the textArea the item dropped.
So if i choose to drop the item b, I would like to have b written in the textArea.
I have two problems.
1°) I have an error
Exception in thread "JavaFX Application Thread" java.lang.IllegalArgumentException: Only serializable objects or ByteBuffer can be used as data with data format []
2°) My setOn events don't run at all. At any time, an event is detected.
package application;
import java.io.Serializable;
import javafx.application.Application;
import javafx.geometry.Insets;
import javafx.scene.Scene;
import javafx.scene.control.*;
import javafx.scene.input.*;
import javafx.scene.layout.HBox;
import javafx.stage.Stage;
public class testDragAndDropTreeView extends Application implements Serializable {
private final TreeView<String> tree = new TreeView<String>();
private final TextArea text = new TextArea();
private static final DataFormat DATAFORMAT = new DataFormat();
@Override
public void start(Stage Stage) {
HBox hbox = new HBox();
hbox.setPadding(new Insets(20));
TreeItem<String> a = new TreeItem<String>("a");
TreeItem<String> b = new TreeItem<String>("b");
TreeItem<String> c = new TreeItem<String>("c");
TreeItem<String> root = new TreeItem<String>("Root");
root.getChildren().addAll(a, b, c);
root.setExpanded(true);
tree.setRoot(root);
tree.setOnDragDetected(event -> {
Dragboard db = tree.startDragAndDrop(TransferMode.ANY);
ClipboardContent content = new ClipboardContent();
content.put(DATAFORMAT, tree.getSelectionModel().getSelectedItem());
db.setContent(content);
});
text.setOnDragOver(event -> {
if (event.getGestureSource() != text && event.getDragboard().hasContent(DATAFORMAT)) {
event.acceptTransferModes(TransferMode.ANY);
}
event.consume();
});
text.setOnDragDropped(event -> {
Dragboard db = event.getDragboard();
boolean success = false;
if (db.hasContent(DATAFORMAT)) {
Person droppedPerson = (Person) db.getContent(DATAFORMAT);
text.appendText(droppedPerson.getName() + "\n");
success = true;
}
event.setDropCompleted(success);
event.consume();
});
tree.setCellFactory(param -> {
return new TreeCell<String>() {
@Override
protected void updateItem(String item, boolean empty) {
super.updateItem(item, empty);
if (item == null) {
setStyle(null);
setGraphic(null);
setText(null);
return;
}
setText(item);
}
};
});
hbox.getChildren().addAll(tree, text);
Stage.setScene(new Scene(hbox));
Stage.show();
}
public static void main(String[] args) {
launch(args);
}
}
A few of observations:
Person
, I just changed it to String.Stage
variable Stage
exactly the same case as the class name, as that is really confusing.tree.setShowRoot(false)
.Example
Test this modification of your code and verify if it does what you want. If it is not exactly what you want, perhaps you can use it as a new starting point and tweak it how you want.
import java.io.Serializable;
import java.util.Map;
import javafx.application.Application;
import javafx.geometry.Insets;
import javafx.scene.Scene;
import javafx.scene.control.*;
import javafx.scene.input.*;
import javafx.scene.layout.HBox;
import javafx.stage.Stage;
public class DragAndDropTreeViewApp extends Application implements Serializable {
private static final DataFormat DATA_FORMAT = DataFormat.PLAIN_TEXT;
private final TreeView<String> tree = new TreeView<>();
private final TextArea text = new TextArea();
@Override
public void start(Stage stage) {
HBox hbox = new HBox();
hbox.setPadding(new Insets(20));
TreeItem<String> a = new TreeItem<>("a");
TreeItem<String> b = new TreeItem<>("b");
TreeItem<String> c = new TreeItem<>("c");
TreeItem<String> root = new TreeItem<>("Root");
//noinspection unchecked
root.getChildren().addAll(a, b, c);
root.setExpanded(true);
tree.setRoot(root);
tree.setOnDragDetected(event -> {
if (tree.getSelectionModel().getSelectedItem() != null) {
Dragboard db = tree.startDragAndDrop(TransferMode.ANY);
db.setContent(
Map.of(
DATA_FORMAT,
tree.getSelectionModel().getSelectedItem().getValue()
)
);
}
});
text.setOnDragOver(event -> {
if (event.getGestureSource() != text && event.getDragboard().hasContent(DATA_FORMAT)) {
event.acceptTransferModes(TransferMode.ANY);
}
event.consume();
});
text.setOnDragDropped(event -> {
Dragboard db = event.getDragboard();
boolean success = false;
if (db.hasContent(DATA_FORMAT)) {
String droppedPerson = (String) db.getContent(DATA_FORMAT);
text.appendText(droppedPerson + "\n");
success = true;
}
event.setDropCompleted(success);
event.consume();
});
tree.setCellFactory(param -> new TreeCell<>() {
@Override
protected void updateItem(String item, boolean empty) {
super.updateItem(item, empty);
if (empty || item == null) {
setStyle(null);
setGraphic(null);
setText(null);
return;
}
setText(item);
}
});
hbox.getChildren().addAll(tree, text);
stage.setScene(new Scene(hbox));
stage.show();
}
public static void main(String[] args) {
launch(args);
}
}