#java #treeview
#java #просмотр дерева
Вопрос:
Я знаю, что этот вопрос задавался несколько раз, но я не смог получить помощь ни из одной статьи.
Мой основной.FXML — это
<?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>
Мой Controller.java это
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());
}
}
Мой Main.java это
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);
}
}
Я видел статью, в которой рассказывается, как добавить функцию перетаскивания в TreeItem через TreeCell, добавив свойство Cell. Но процессы были довольно сложными, и я, будучи непрофессионалом в JavaFX, не смог их понять.
Итак, будет весьма полезно, если кто-нибудь сможет мне помочь с этим.
Заранее спасибо.
Ответ №1:
Добавьте в свой код контроллера, отвечающий за настройку пользовательской фабрики ячеек, которая будет прикреплять обработчики к событиям перетаскивания / 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;
});
Основные обработчики взяты со страницы javadoc DragEvent:
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();
}
Комментарии:
1. Мне нужна еще одна помощь по этой теме. Я хочу, чтобы в консоли, на которой выполняется перетаскивание, было напечатано имя узла, а также имя узла, на который удален исходный узел. Короче говоря, мне нужны имена исходного и целевого узлов. Заранее спасибо
2. используйте: (TreeCell<Строка>) DragEvent. getSourceGesture() , чтобы получить доступ к вашей TreeCell. Для целевого узла это то же самое, только имя метода — getTargetGesture
3. Я пробовал так, как вы сказали, но я столкнулся с двумя проблемами :
4. Проблема № 1 : я использовал System.out.println((TreeCell<String>) DragEvent.getSourceGesture()). Здесь вывод был таким: «TextFieldTreeCell@fff603[styleClass=cell indexed-cell tree-cell text-field-tree-cell]’NodeB'», Проблема № 2: я также использовал System.out.println(((TreeCell<String>)DragEvent.getGestureTarget()).getText()); Здесь в выводе: только onDragDetected активен, ни DragOver, ни DragDropped не активны.
5. 1. TreeCell имеет метод GetItem, который возвращает значение типа в данном случае строку «NodeB», 2. Перетаскивание / удаление может быть неактивным, если вы ничего не помещаете в Dragboard или не вводите null в обработчик обнаружения перетаскивания.
Ответ №2:
С помощью @kozmatteo я смог приобрести функцию перетаскивания TreeView в JavaFX. Код контроллера выглядит следующим образом :
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()
amp;amp; !targetNode.equalsIgnoreCase(source.getItem()))
{
System.out.println("Dropped on: " targetNode);
success = true;
}
event.setDropCompleted(success);
event.consume();
}
}
Демонстрация приведенного выше кода:
Но одна из проблем, которая возникает, если onDragOver
немного изменить код. Я хочу напечатать имя узла, на который перетаскивается перетаскиваемый узел.
onDragOver();
изменен метод:
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();
}
Демонстрация после добавления кода выше:
Наконец:
Я хочу знать имя узла, на который перетаскивается исходный код. Если кто-нибудь может помочь мне с этим, то это будет очень полезно.