Дизайн, который я имел в виду, примерно такой: есть TreeView<E>
, где E
— это класс-оболочка, реализация которого может выглядеть так:
public class E {
private int key;
private String value;
public E(int key, String value) {
this.key = key;
this.value = value;
}
public int getKey(){
return key;
}
public String getValue() {
return value;
}
public String toString(){
return value;
}
}
Итак, TreeView<E>
будет содержать кучу TreeItem<E>
экземпляров. И метод toString()
E
отображает значение.
И когда вы нажимаете любой из элементов дерева, я хочу, чтобы TableView<ObservableList<String>>
отображалось под выбранным TreeItem<E>
, содержащим все строки из БД, которая связана со значением ключа TreeItem<E>
.
Это возможно? Я знаю, что TreeTableView
— достойный вариант, но я не хочу показывать какие-либо столбцы, пока не нажму один из элементов дерева. И я хочу, чтобы у каждого TreeItem<E>
была своя таблица. Хотя, для справки, все таблицы будут иметь одинаковые столбцы, просто разное количество строк.
Обновление: с помощью @Uluk Biy мне удалось реализовать решение, но оно содержит одну ошибку.
Проблема в том, что когда я нажимаю TreeItem в TreeView, выбирается узел, который находится на два шага ниже первого узла, который не отображается в области прокрутки, когда я нажимаю TreeItem (TreeView автоматически содержит панель прокрутки). ). Поэтому, если я растяну окно так, чтобы было скрыто менее 3 элементов дерева, ничего не будет отображаться. И дело не в том, что TableView отображается не в том месте, проблема в том, что не выбран правильный элемент дерева (я знаю это, потому что распечатал значение ключа.
Вот SSCCE, который показывает эту ошибку. Выберите обертку 1 в таблице, и обертка 6 будет выбрана. Если вы измените размер TreeView так, чтобы было скрыто менее трех элементов TreeItem, ничего не будет выбрано.
import javafx.application.Application;
import javafx.beans.property.SimpleStringProperty;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.scene.Scene;
import javafx.scene.control.Label;
import javafx.scene.control.TableColumn;
import javafx.scene.control.TableView;
import javafx.scene.control.TreeCell;
import javafx.scene.control.TreeItem;
import javafx.scene.control.TreeView;
import javafx.scene.layout.AnchorPane;
import javafx.scene.layout.VBox;
import javafx.stage.Stage;
import javafx.util.Callback;
public class SSCCE extends Application {
private Stage primaryStage;
private AnchorPane rootLayout;
private TreeView<Wrapper> overview;
public void start(Stage primaryStage) {
this.primaryStage = primaryStage;
this.primaryStage.setTitle("SSCCE");
initRootLayout();
showTreeView();
}
public void initRootLayout() {
rootLayout = new AnchorPane();
rootLayout.setPrefSize(300, 200);
Scene scene = new Scene(rootLayout);
primaryStage.setScene(scene);
primaryStage.show();
}
ObservableList<String> columns = FXCollections.observableArrayList();
ObservableList<ObservableList<String>> data = FXCollections.observableArrayList();
ObservableList<Wrapper> items = FXCollections.observableArrayList();
private void showTreeView() {
// Dummy values
columns.addAll("key", "text");
data.add(FXCollections.observableArrayList("1", "test"));
data.add(FXCollections.observableArrayList("1", "test2"));
data.add(FXCollections.observableArrayList("2", "test3"));
data.add(FXCollections.observableArrayList("2", "test4"));
data.add(FXCollections.observableArrayList("3", "test5"));
data.add(FXCollections.observableArrayList("3", "test6"));
data.add(FXCollections.observableArrayList("4", "test7"));
data.add(FXCollections.observableArrayList("4", "test8"));
data.add(FXCollections.observableArrayList("5", "test9"));
data.add(FXCollections.observableArrayList("5", "test10"));
data.add(FXCollections.observableArrayList("6", "test11"));
data.add(FXCollections.observableArrayList("6", "test12"));
items.addAll(new Wrapper(1, "wrapper 1"), new Wrapper(2, "wrapper 2"), new Wrapper(3, "wrapper 3"), new Wrapper(4, "wrapper 4"), new Wrapper(5, "wrapper 5"), new Wrapper(6, "wrapper 6"));
TreeItem<Wrapper> root = new TreeItem<Wrapper>();
overview = new TreeView<Wrapper>(root);
overview.setPrefHeight(75);
overview.setCellFactory(new Callback<TreeView<Wrapper>, TreeCell<Wrapper>>() {
@Override
public TreeCell<Wrapper> call(TreeView<Wrapper> stringTreeView) {
TreeCell<Wrapper> treeCell = new TreeCell<Wrapper>() {
@Override
protected void updateItem(Wrapper item, boolean empty) {
super.updateItem(item, empty);
if (empty || item == null) {
setText(null);
setGraphic(null);
} else {
if (getTreeItem().isLeaf() && isSelected()) {
setText(null);
// A debug text that proves that the wrong item is being selected.
System.out.println("Selected wrapper: " + item);
TableView<ObservableList<String>> table = new TableView<ObservableList<String>>();
for (int i = 0; i < columns.size(); i++) {
final int j = i;
TableColumn<ObservableList<String>, String> column = new TableColumn<ObservableList<String>, String>(
columns.get(i));
column.setCellValueFactory((
TableColumn.CellDataFeatures<ObservableList<String>, String> param) -> new SimpleStringProperty(
param.getValue().get(j)
.toString()));
table.getColumns()
.add(column);
}
ObservableList<ObservableList<String>> selected_data = FXCollections
.observableArrayList();
for(int i = 0; i < data.size(); i++) {
if(Integer.parseInt(data.get(i).get(0)) == item.getKey()) {
selected_data.add(data.get(i));
}
}
table.setItems(selected_data);
VBox vbox = new VBox(new Label(item
.getValue()), table);
setGraphic(vbox);
} else {
setText(item.getValue());
setGraphic(null);
}
}
}
};
return treeCell;
}
});
for (int i = 0; i < items.size(); i++) {
TreeItem<Wrapper> target = new TreeItem<Wrapper>(items.get(i));
root.getChildren().add(target);
}
overview.setShowRoot(false);
rootLayout.getChildren().add(overview);
}
public static void main(String[] args) {
launch(args);
}
}
class Wrapper {
private int key;
private String value;
Wrapper(int key, String value) {
this.key = key;
this.value = value;
}
int getKey() {
return key;
}
String getValue() {
return value;
}
public String toString() {
return "Wrapper " + key;
}
}