TreeView

Последнее обновление: 23.06.2018

Класс javafx.scene.control.TreeView<T> позволяет отображать данные в виде дерева. Параметр T в угловых скобках указывает на тип элементов, которые будут храниться в TreeView.

Для создания иерархичного представления данных в виде дерева TreeView должен определять один корневой узел в виде объекта TreeItem<T>. В этот узел затем помещаются остальные узлы, которые тоже представляют TreeItem и которые содержат сами хранимые данные.

Чтобы определить объект TreeView, мы можем использовать один из двух конструкторов:

  • TreeView(): создает пустое дерево

  • TreeView​(TreeItem<T> root): создает дерево, для которого устанавливается корневой узел root

Если корневой узел не был устанолен при создании TreeView, то его можно установить впоследствии с помощью метода

void setRoot​(TreeItem<T> value)

Определим простейший TreeView:

import javafx.application.Application;
import javafx.stage.Stage;
import javafx.scene.Scene;
import javafx.scene.layout.FlowPane;
import javafx.scene.control.TreeView;
import javafx.scene.control.TreeItem;
import javafx.geometry.Orientation;
 
public class Main extends Application{
	
    public static void main(String[] args) {
         
        Application.launch(args);
    }
     
    @Override
    public void start(Stage stage) throws Exception {
		
		// определяем корневой узел
		TreeItem<String> rootTreeNode = new TreeItem<String>("Languages");
		
		// определяем набор вложенных узлов
		TreeItem<String> germanics = new TreeItem<String>("Germanic");
		germanics.getChildren().add(new TreeItem<String>("German"));
		germanics.getChildren().add(new TreeItem<String>("English"));
		
		TreeItem<String> romans = new TreeItem<String>("Roman");
		romans.getChildren().add(new TreeItem<String>("French"));
		romans.getChildren().add(new TreeItem<String>("Spanish"));
		romans.getChildren().add(new TreeItem<String>("Italian"));
		
		// добавляем узлы в корневой узел
		rootTreeNode.getChildren().add(germanics);
		rootTreeNode.getChildren().add(romans);
		
		// устанавливаем корневой узел для TreeView
		TreeView<String> langsTreeView = new TreeView<String>(rootTreeNode);
		langsTreeView.setPrefSize(150, 200);
		FlowPane root = new FlowPane(10, 10, langsTreeView);
		
        Scene scene = new Scene(root, 300, 250);
         
        stage.setScene(scene);
        stage.setTitle("TreeView in JavaFX");
        stage.show();
    }
}

В данном случае в дереве хранятся строки - объекты String, поэтому все объекты TreeItem и TreeView типизируются типом String.

TreeView in JavaFX

Получение выбранных элементов

По умолчанию TreeView позволяет выбрать одномоментно один элемент. Но напрямую мы не можем получить из TreeView выделенный элемент. Для этого нам вначале надо получить модель выбора элементов с помощью метода

MultipleSelectionModel<TreeItem<T>> getSelectionModel()

Затем с помощью метода getSelectedItems() у объекта MultipleSelectionModel можно получить выделенные элементы TreeItem. Хотя по умолчанию TreeView поддеживает выбор только одного элемента, но мы можем задать выбо сразу нескольких элементов с помощью дугого метода MultipleSelectionModel:

void setSelectionMode(SelectionMode mode)

В этот метод передается значение SelectionMode (например, SelectionMode.MULTIPLE для множественного выбора).

Итак, выведем в элемент Label все выбранные в TreeView элементы:

import javafx.application.Application;
import javafx.stage.Stage;
import javafx.scene.Scene;
import javafx.scene.layout.FlowPane;
import javafx.scene.control.Label;
import javafx.scene.control.Button;
import javafx.scene.control.TreeView;
import javafx.scene.control.TreeItem;
import javafx.scene.control.MultipleSelectionModel;
import javafx.scene.control.SelectionMode;
import javafx.geometry.Orientation;
 
public class Main extends Application{
	
    public static void main(String[] args) {
         
        Application.launch(args);
    }
     
    @Override
    public void start(Stage stage) throws Exception {
		
		TreeItem<String> rootTreeNode = new TreeItem<String>("Languages");
		
		TreeItem<String> germanics = new TreeItem<String>("Germanic");
		germanics.getChildren().add(new TreeItem<String>("German"));
		germanics.getChildren().add(new TreeItem<String>("English"));
		
		TreeItem<String> romans = new TreeItem<String>("Roman");
		romans.getChildren().add(new TreeItem<String>("French"));
		romans.getChildren().add(new TreeItem<String>("Spanish"));
		romans.getChildren().add(new TreeItem<String>("Italian"));
		
		rootTreeNode.getChildren().add(germanics);
		rootTreeNode.getChildren().add(romans);
		
		TreeView<String> langsTreeView = new TreeView<String>(rootTreeNode);
		langsTreeView.setPrefSize(150, 200);
		
		// получаем модель выбора
		MultipleSelectionModel<TreeItem<String>> selectionModel = langsTreeView.getSelectionModel();
		// устанавливаем множественный выбор (если он необходим)
		selectionModel.setSelectionMode(SelectionMode.MULTIPLE);
		
		Label lbl = new Label();
		Button btn = new Button("Get Selected");
		btn.setOnAction(event -> {
			
			String selected = "";
			// перебираем выбанные элементы
			for(TreeItem<String> item : selectionModel.getSelectedItems()){
				
				selected += item.getValue() + " ";
			}
			lbl.setText("Selected: " + selected);
		});
		
		FlowPane root = new FlowPane(Orientation.VERTICAL, 10, 10, langsTreeView, lbl, btn);
		
        Scene scene = new Scene(root, 300, 250);
         
        stage.setScene(scene);
        stage.setTitle("TreeView in JavaFX");
        stage.show();
    }
}

Следует учитывать, что здесь метод getSelectedItems у MultipleSelectionModel возвращает объекты TreeItem. Поэтому чтобы получить непосредственно само строковое значение из TreeItem, надо использовать его метод getValue().

Получение выбранных элементов в TreeView в JavaFX

Также мы можем установить слушатель, который будет обрабатывать автоматически выбор элементов в TreeView. Для этого у объекта MultipleSelectionModel вначале надо получить послушиваемое свойство с помощью метода selectedItemProperty() и затем к нему прикрепить слушатель с помощью метода addListener():

import javafx.application.Application;
import javafx.stage.Stage;
import javafx.scene.Scene;
import javafx.scene.layout.FlowPane;
import javafx.scene.control.Label;
import javafx.scene.control.Button;
import javafx.scene.control.TreeView;
import javafx.scene.control.TreeItem;
import javafx.scene.control.MultipleSelectionModel;
import javafx.scene.control.SelectionMode;
import javafx.geometry.Orientation;
import javafx.beans.value.ObservableValue;
import javafx.beans.value.ChangeListener;

public class Main extends Application{
	
    public static void main(String[] args) {
         
        Application.launch(args);
    }
     
    @Override
    public void start(Stage stage) throws Exception {
		
		TreeItem<String> rootTreeNode = new TreeItem<String>("Languages");
		
		TreeItem<String> germanics = new TreeItem<String>("Germanic");
		germanics.getChildren().add(new TreeItem<String>("German"));
		germanics.getChildren().add(new TreeItem<String>("English"));
		
		TreeItem<String> romans = new TreeItem<String>("Roman");
		romans.getChildren().add(new TreeItem<String>("French"));
		romans.getChildren().add(new TreeItem<String>("Spanish"));
		romans.getChildren().add(new TreeItem<String>("Italian"));
		
		rootTreeNode.getChildren().add(germanics);
		rootTreeNode.getChildren().add(romans);
		
		TreeView<String> langsTreeView = new TreeView<String>(rootTreeNode);
		langsTreeView.setPrefSize(150, 200);
		
		MultipleSelectionModel<TreeItem<String>> selectionModel = langsTreeView.getSelectionModel();
		
		Label lbl = new Label();
		// устанавливаем слушатель для отслеживания изменений
        selectionModel.selectedItemProperty().addListener(new ChangeListener<TreeItem<String>>(){
             
            public void changed(ObservableValue<? extends TreeItem<String>> changed, 
								TreeItem<String> oldValue, TreeItem<String> newValue){
                 
                lbl.setText("Selected: " + newValue.getValue());
            }
        });
		
		FlowPane root = new FlowPane(Orientation.VERTICAL, 10, 10, langsTreeView, lbl);
		
        Scene scene = new Scene(root, 300, 250);
         
        stage.setScene(scene);
        stage.setTitle("TreeView in JavaFX");
        stage.show();
    }
}

В методе addListener припрекляется слушатель, который реализует интерфейс ChangeListener. В данном случае интерфейс типизируется типом TreeItem<String>, так как все выбираемые элементы педставляют этот тип. А в методе changed этого интерфейса с помощью параметра newValue мы можем получить новое выбранное значение и что-то с ним сделать, например, отобразить на метке. Также можно получить ранее выбранное значение через параметр oldValue.

Выбор в TreeView в JavaFX

Получение полного пути к узлу

Класс TreeItem, который представляет отдельный узел в TreeView, имеет возможности для получения полного пути к этому узлу в рамках TreeView с учетом родительских узлов. В частности, для получения родительского объекта TreeItem в классе определен метод getParent():

import javafx.application.Application;
import javafx.stage.Stage;
import javafx.scene.Scene;
import javafx.scene.layout.FlowPane;
import javafx.scene.control.Label;
import javafx.scene.control.Button;
import javafx.scene.control.TreeView;
import javafx.scene.control.TreeItem;
import javafx.scene.control.MultipleSelectionModel;
import javafx.scene.control.SelectionMode;
import javafx.geometry.Orientation;
import javafx.beans.value.ObservableValue;
import javafx.beans.value.ChangeListener;

public class Main extends Application{
	
    public static void main(String[] args) {
         
        Application.launch(args);
    }
     
    @Override
    public void start(Stage stage) throws Exception {
		
		TreeItem<String> rootTreeNode = new TreeItem<String>("Languages");
		rootTreeNode.setExpanded(true);	 // раскрываем узел
		
		TreeItem<String> germanics = new TreeItem<String>("Germanic");
		germanics.getChildren().add(new TreeItem<String>("German"));
		germanics.getChildren().add(new TreeItem<String>("English"));
		
		TreeItem<String> romans = new TreeItem<String>("Roman");
		romans.getChildren().add(new TreeItem<String>("French"));
		romans.getChildren().add(new TreeItem<String>("Spanish"));
		romans.getChildren().add(new TreeItem<String>("Italian"));
		
		rootTreeNode.getChildren().add(germanics);
		rootTreeNode.getChildren().add(romans);
		
		TreeView<String> langsTreeView = new TreeView<String>(rootTreeNode);
		langsTreeView.setPrefSize(150, 200);
		
		MultipleSelectionModel<TreeItem<String>> selectionModel = langsTreeView.getSelectionModel();
		
		Label lbl = new Label();
		
        selectionModel.selectedItemProperty().addListener(new ChangeListener<TreeItem<String>>(){
             
            public void changed(ObservableValue<? extends TreeItem<String>> changed, 
								TreeItem<String> oldValue, TreeItem<String> newValue){
                 if(newValue != null){
					 
					 String path = newValue.getValue();
					 TreeItem<String> parent = newValue.getParent();
					 while(parent != null){
						 path = parent.getValue() + " / " + path;
						 parent = parent.getParent();
					 }
					lbl.setText(path);
				 }
            }
        });
		
		FlowPane root = new FlowPane(Orientation.VERTICAL, 10, 10, langsTreeView, lbl);
		
        Scene scene = new Scene(root, 300, 250);
         
        stage.setScene(scene);
        stage.setTitle("TreeView in JavaFX");
        stage.show();
    }
}
TreeView и TreeItem в JavaFX
Помощь сайту
Юмани:
410011174743222
Перевод на карту
Номер карты:
4048415020898850