Reputation: 320
I know this question has been asked a multiple times, but I was unable to get help from any of the article.
My Main.FXML is
<?import javafx.scene.control.*?>
<?import java.lang.*?>
<?import javafx.scene.layout.*?>
<?import javafx.scene.layout.AnchorPane?>
<AnchorPane prefHeight="400.0" prefWidth="600.0" xmlns="http://javafx.com/javafx/8" xmlns:fx="http://javafx.com/fxml/1" fx:controller="sample.Controller">
<children>
<TreeView fx:id="treeView" layoutX="51.0" layoutY="24.0" onContextMenuRequested="#mouseClick" onMouseClicked="#mouseClick" prefHeight="352.0" prefWidth="493.0" />
</children>
</AnchorPane>
My Controller.java is
import javafx.fxml.FXML;
import javafx.fxml.Initializable;
import javafx.scene.control.TreeItem;
import javafx.scene.control.TreeView;
import javafx.scene.input.MouseEvent;
import java.net.URL;
import java.util.ResourceBundle;
public class Controller implements Initializable
{
@FXML TreeView<String> treeView;
@Override
public void initialize(URL location, ResourceBundle resources)
{
TreeItem<String> root = new TreeItem<>("root");
TreeItem<String> nodeA = new TreeItem<>("nodeA");
TreeItem<String> nodeB = new TreeItem<>("nodeB");
TreeItem<String> nodeC = new TreeItem<>("nodeC");
root.getChildren().add(nodeA);
root.getChildren().add(nodeB);
root.getChildren().add(nodeC);
treeView.setRoot(root);
root.setExpanded(true);
}
@FXML
private void mouseClick(MouseEvent mouseEvent)
{
TreeItem<String> item = treeView.getSelectionModel().getSelectedItem();
System.out.println(item.getValue());
}
}
My Main.java is
import javafx.application.Application;
import javafx.fxml.FXMLLoader;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.stage.Stage;
public class Main extends Application {
@Override
public void start(Stage primaryStage) throws Exception{
Parent root = FXMLLoader.load(getClass().getResource("sample.fxml"));
Scene scene = new Scene(root);
primaryStage.setScene(scene);
primaryStage.show();
}
public static void main(String[] args) {
launch(args);
}
}
I have seen article that teaches how to add the Drag and Drop feature to TreeItem via TreeCell by adding Cell Property. But the processes were quiet complicated and I being a layman to JavaFX was unable to understand those.
So, it will be quite helpful if anyone can help me out with this.
Thanks in Advance.
Upvotes: 0
Views: 186
Reputation: 320
With the help of @kozmatteo I was able to acquire the drag and drop feature of TreeView in JavaFX. The Controller code is as below :
Controller.java
import javafx.fxml.FXML;
import javafx.fxml.Initializable;
import javafx.scene.control.TreeCell;
import javafx.scene.control.TreeItem;
import javafx.scene.control.TreeView;
import javafx.scene.control.cell.TextFieldTreeCell;
import javafx.scene.input.*;
import java.net.URL;
import java.util.ResourceBundle;
public class Controller implements Initializable
{
@FXML TreeView<String> treeView;
private TreeCell<String> source, treeCell;
@Override
public void initialize(URL location, ResourceBundle resources)
{
TreeItem<String> root = new TreeItem<>("root");
TreeItem<String> nodeA = new TreeItem<>("nodeA");
TreeItem<String> nodeB = new TreeItem<>("nodeB");
TreeItem<String> nodeC = new TreeItem<>("nodeC");
root.getChildren().add(nodeA);
root.getChildren().add(nodeB);
root.getChildren().add(nodeC);
treeView.setRoot(root);
root.setExpanded(true);
treeView.setCellFactory(param -> {
// creating cell from deafult factory
treeCell = TextFieldTreeCell.forTreeView().call(param);
// setting handlers
treeCell.setOnDragDetected(this::onDragDetected);
treeCell.setOnDragOver(this::onDragOver);
treeCell.setOnDragDropped(this::onDragDropped);
return treeCell;
});
}
private void onDragDetected(MouseEvent event)
{
source = (TreeCell<String>) event.getSource();
Dragboard db = source.startDragAndDrop(TransferMode.ANY);
ClipboardContent content = new ClipboardContent();
content.putString(source.getItem());
db.setContent(content);
System.out.println("Dragging: " + db.getString());
event.consume();
}
private void onDragOver(DragEvent dragEvent)
{
Dragboard db = dragEvent.getDragboard();
if (db.hasString())
{
dragEvent.acceptTransferModes(TransferMode.COPY);
}
dragEvent.consume();
}
private void onDragDropped(DragEvent event)
{
Dragboard db = event.getDragboard();
String targetNode = ((TreeCell<String>)event.getGestureTarget()).getItem();
boolean success = false;
if (db.hasString()
&& !targetNode.equalsIgnoreCase(source.getItem()))
{
System.out.println("Dropped on: " + targetNode);
success = true;
}
event.setDropCompleted(success);
event.consume();
}
}
Demonstration for the code above:
But One of the problem that occurs if the onDragOver
code is changed a bit. I want to print the name of the node upon which the dragging node is dragged over.
onDragOver();
method changed:
private void onDragOver(DragEvent dragEvent)
{
Dragboard db = dragEvent.getDragboard();
if (db.hasString())
{
dragEvent.acceptTransferModes(TransferMode.COPY);
String targetNode = ((TreeCell<String>)event.getGestureTarget()).getItem(); // On adding this piece of code the DragOver event is not working.
}
dragEvent.consume();
}
Demonstration after adding the code above:
Finally:
I want to know the name of the node on which the source is being dragged over. If anyone can help me with this then it will be very much helpful.
Upvotes: 0
Reputation: 41
Add in your Controller code responsible for setting a custom cell factory, that will attach handlers to Drag/MouseEvents.
treeView.setCellFactory(param -> {
// creating cell from deafult factory
TreeCell<String> treeCell = TextFieldTreeCell.forTreeView().call(param);
// setting handlers
treeCell.setOnDragDetected(this::onDragDetected);
treeCell.setOnDragOver(this::onDragOver);
treeCell.setOnDragDropped(this::onDragDropped);
return treeCell;
});
Basic handlers taken from DragEvent javadoc page:
private void onDragDetected(MouseEvent event) {
TreeCell<String> source = (TreeCell<String>) event.getSource();
Dragboard db = source.startDragAndDrop(TransferMode.ANY);
ClipboardContent content = new ClipboardContent();
content.putString(source.getItem());
db.setContent(content);
event.consume();
}
private void onDragOver(DragEvent dragEvent) {
Dragboard db = dragEvent.getDragboard();
if (db.hasString()) {
dragEvent.acceptTransferModes(TransferMode.COPY);
}
dragEvent.consume();
}
private void onDragDropped(DragEvent event) {
Dragboard db = event.getDragboard();
boolean success = false;
if (db.hasString()) {
System.out.println("Dropped: " + db.getString());
success = true;
}
event.setDropCompleted(success);
event.consume();
}
Upvotes: 1