代码:public void showTours(List<Tour> pTours) { treeViewPane.getSelectionModel().selectedItemProperty().addListener(treeItemChangeListener); TreeItem tTreeRoot = new TreeItem<>("Root", new ImageView(Icons.getIcon24("truck_blue.png"))); tTreeRoot.setExpanded(true); treeViewPane.setRoot(tTreeRoot); for (Tour tTour : pTours) { TreeItem<Object> tTourItem = new TreeItem<>(tTour); tTreeRoot.getChildren().add(tTourItem); if (tTour.getDeliveries() != null) { for (Delivery tDelivery : tTour.getDeliveries()) { TreeItem<Object> tDeliveryItem = new TreeItem<>(tDelivery); tTourItem.getChildren().add(tDeliveryItem); } } }}private final ChangeListener<TreeItem> treeItemChangeListener = (observable, oldValue, newValue) -> { if (newValue != null && newValue.getValue() instanceof Tour){ Tour selectedTour = (Tour) newValue.getValue(); reloadTabContent(selectedTour); }};希望您能帮助我.如果您可以向我展示示例代码,我将非常高兴:)谢谢解决方案在JavaFX中修改任何控件中的选择行为似乎有些麻烦.但是执行此操作的正确"方法是为树定义自定义选择模型.最简单的方法是包装默认选择模型,然后将方法调用委托给它,如果选择索引用于不应选择的项目,则否决选择.最好在调用select方法时尽可能选择一些内容,否则键盘导航会中断.这是一个实现:import java.util.List;import java.util.stream.Collectors;import java.util.stream.IntStream;import java.util.stream.Stream;import javafx.application.Application;import javafx.collections.ObservableList;import javafx.scene.Scene;import javafx.scene.control.MultipleSelectionModel;import javafx.scene.control.SelectionMode;import javafx.scene.control.TreeItem;import javafx.scene.control.TreeView;import javafx.scene.layout.BorderPane;import javafx.stage.Stage;public class CustomTreeSelectionModelExample extends Application { @Override public void start(Stage primaryStage) { TreeItem<Object> root = new TreeItem<>("Root"); for (int i = 1 ; i <= 5 ; i++) { TreeItem<Object> item = new TreeItem<>(new Tour("Tour "+i)); for (int j = 1 ; j <= 5; j++) { Delivery delivery = new Delivery("Delivery "+j); item.getChildren().add(new TreeItem<>(delivery)); } root.getChildren().add(item); } TreeView<Object> tree = new TreeView<>(); tree.setSelectionModel(new TourSelectionModel(tree.getSelectionModel(), tree)); tree.setRoot(root); primaryStage.setScene(new Scene(new BorderPane(tree), 400, 400)); primaryStage.show(); } public static class TourSelectionModel extends MultipleSelectionModel<TreeItem<Object>> { private final MultipleSelectionModel<TreeItem<Object>> selectionModel ; private final TreeView<Object> tree ; public TourSelectionModel(MultipleSelectionModel<TreeItem<Object>> selectionModel, TreeView<Object> tree) { this.selectionModel = selectionModel ; this.tree = tree ; selectionModeProperty().bindBidirectional(selectionModel.selectionModeProperty()); } @Override public ObservableList<Integer> getSelectedIndices() { return selectionModel.getSelectedIndices() ; } @Override public ObservableList<TreeItem<Object>> getSelectedItems() { return selectionModel.getSelectedItems() ; } @Override public void selectIndices(int index, int... indices) { List<Integer> indicesToSelect = Stream.concat(Stream.of(index), IntStream.of(indices).boxed()) .filter(i -> tree.getTreeItem(i).getValue() instanceof Tour) .collect(Collectors.toList()); if (indicesToSelect.isEmpty()) { return ; } selectionModel.selectIndices(indicesToSelect.get(0), indicesToSelect.stream().skip(1).mapToInt(Integer::intValue).toArray()); } @Override public void selectAll() { List<Integer> indicesToSelect = IntStream.range(0, tree.getExpandedItemCount()) .filter(i -> tree.getTreeItem(i).getValue() instanceof Tour) .boxed() .collect(Collectors.toList()); if (indicesToSelect.isEmpty()) { return ; } selectionModel.selectIndices(0, indicesToSelect.stream().skip(1).mapToInt(Integer::intValue).toArray()); } @Override public void selectFirst() { IntStream.range(0, tree.getExpandedItemCount()) .filter(i -> tree.getTreeItem(i).getValue() instanceof Tour) .findFirst() .ifPresent(selectionModel::select); } @Override public void selectLast() { IntStream.iterate(tree.getExpandedItemCount() - 1, i -> i - 1) .limit(tree.getExpandedItemCount()) .filter(i -> tree.getTreeItem(i).getValue() instanceof Tour) .findFirst() .ifPresent(selectionModel::select); } @Override public void clearAndSelect(int index) { int toSelect = index ; int direction = selectionModel.getSelectedIndex() < index ? 1 : -1 ; while (toSelect >= 0 && toSelect < tree.getExpandedItemCount() && ! (tree.getTreeItem(toSelect).getValue() instanceof Tour)) { toSelect = toSelect + direction ; } if (toSelect >= 0 && toSelect < tree.getExpandedItemCount()) { selectionModel.clearAndSelect(toSelect); } } @Override public void select(int index) { int toSelect = index ; int direction = selectionModel.getSelectedIndex() < index ? 1 : -1 ; while (toSelect >= 0 && toSelect < tree.getExpandedItemCount() && ! (tree.getTreeItem(toSelect).getValue() instanceof Tour)) { toSelect = toSelect + direction ; } if (toSelect >= 0 && toSelect < tree.getExpandedItemCount()) { selectionModel.select(toSelect); } } @Override public void select(TreeItem<Object> obj) { if (obj.getValue() instanceof Tour) { selectionModel.select(obj); } } @Override public void clearSelection(int index) { selectionModel.clearSelection(index); } @Override public void clearSelection() { selectionModel.clearSelection(); } @Override public boolean isSelected(int index) { return selectionModel.isSelected(index); } @Override public boolean isEmpty() { return selectionModel.isEmpty(); } @Override public void selectPrevious() { int current = selectionModel.getSelectedIndex() ; if (current > 0) { IntStream.iterate(current - 1, i -> i - 1).limit(current) .filter(i -> tree.getTreeItem(i).getValue() instanceof Tour) .findFirst() .ifPresent(selectionModel::select); } } @Override public void selectNext() { int current = selectionModel.getSelectedIndex() ; if (current < tree.getExpandedItemCount() - 1) { IntStream.range(current + 1, tree.getExpandedItemCount()) .filter(i -> tree.getTreeItem(i).getValue() instanceof Tour) .findFirst() .ifPresent(selectionModel::select); } } } public static class Tour { private final String name ; public Tour(String name) { this.name = name ; } public String getName() { return name ; } @Override public String toString() { return getName(); } } public static class Delivery { private final String name; public Delivery(String name) { this.name = name; } public String getName() { return name; } @Override public String toString() { return getName(); } } public static void main(String[] args) { launch(args); }}I have created a Treeview (javafx), it looks like:I want now, that only the "Tour"-TreeItems be selectable.But I don't know how.I have tried it with a ChangeListener, but I can only with it refresh the content of a Tab (TabPane)...the refresh works fine...but the "Delivery"-TreeItems can be selected :(code:public void showTours(List<Tour> pTours) { treeViewPane.getSelectionModel().selectedItemProperty().addListener(treeItemChangeListener); TreeItem tTreeRoot = new TreeItem<>("Root", new ImageView(Icons.getIcon24("truck_blue.png"))); tTreeRoot.setExpanded(true); treeViewPane.setRoot(tTreeRoot); for (Tour tTour : pTours) { TreeItem<Object> tTourItem = new TreeItem<>(tTour); tTreeRoot.getChildren().add(tTourItem); if (tTour.getDeliveries() != null) { for (Delivery tDelivery : tTour.getDeliveries()) { TreeItem<Object> tDeliveryItem = new TreeItem<>(tDelivery); tTourItem.getChildren().add(tDeliveryItem); } } }}private final ChangeListener<TreeItem> treeItemChangeListener = (observable, oldValue, newValue) -> { if (newValue != null && newValue.getValue() instanceof Tour){ Tour selectedTour = (Tour) newValue.getValue(); reloadTabContent(selectedTour); }};I hope you can help me. If you can show me example code, I will be really happy :)Thank you 解决方案 Modifying the selection behavior in any controls in JavaFX seems to be a bit of a pain; but the "proper" way to do this is to define a custom selection model for the tree. The easiest way to do this is to wrap the default selection model, and delegate the method calls to it, vetoing selection if the selection index is for an item which shouldn't be selected.It's a good idea to select something whenever possible when a select method is called, as otherwise keyboard navigation will break.Here is an implementation:import java.util.List;import java.util.stream.Collectors;import java.util.stream.IntStream;import java.util.stream.Stream;import javafx.application.Application;import javafx.collections.ObservableList;import javafx.scene.Scene;import javafx.scene.control.MultipleSelectionModel;import javafx.scene.control.SelectionMode;import javafx.scene.control.TreeItem;import javafx.scene.control.TreeView;import javafx.scene.layout.BorderPane;import javafx.stage.Stage;public class CustomTreeSelectionModelExample extends Application { @Override public void start(Stage primaryStage) { TreeItem<Object> root = new TreeItem<>("Root"); for (int i = 1 ; i <= 5 ; i++) { TreeItem<Object> item = new TreeItem<>(new Tour("Tour "+i)); for (int j = 1 ; j <= 5; j++) { Delivery delivery = new Delivery("Delivery "+j); item.getChildren().add(new TreeItem<>(delivery)); } root.getChildren().add(item); } TreeView<Object> tree = new TreeView<>(); tree.setSelectionModel(new TourSelectionModel(tree.getSelectionModel(), tree)); tree.setRoot(root); primaryStage.setScene(new Scene(new BorderPane(tree), 400, 400)); primaryStage.show(); } public static class TourSelectionModel extends MultipleSelectionModel<TreeItem<Object>> { private final MultipleSelectionModel<TreeItem<Object>> selectionModel ; private final TreeView<Object> tree ; public TourSelectionModel(MultipleSelectionModel<TreeItem<Object>> selectionModel, TreeView<Object> tree) { this.selectionModel = selectionModel ; this.tree = tree ; selectionModeProperty().bindBidirectional(selectionModel.selectionModeProperty()); } @Override public ObservableList<Integer> getSelectedIndices() { return selectionModel.getSelectedIndices() ; } @Override public ObservableList<TreeItem<Object>> getSelectedItems() { return selectionModel.getSelectedItems() ; } @Override public void selectIndices(int index, int... indices) { List<Integer> indicesToSelect = Stream.concat(Stream.of(index), IntStream.of(indices).boxed()) .filter(i -> tree.getTreeItem(i).getValue() instanceof Tour) .collect(Collectors.toList()); if (indicesToSelect.isEmpty()) { return ; } selectionModel.selectIndices(indicesToSelect.get(0), indicesToSelect.stream().skip(1).mapToInt(Integer::intValue).toArray()); } @Override public void selectAll() { List<Integer> indicesToSelect = IntStream.range(0, tree.getExpandedItemCount()) .filter(i -> tree.getTreeItem(i).getValue() instanceof Tour) .boxed() .collect(Collectors.toList()); if (indicesToSelect.isEmpty()) { return ; } selectionModel.selectIndices(0, indicesToSelect.stream().skip(1).mapToInt(Integer::intValue).toArray()); } @Override public void selectFirst() { IntStream.range(0, tree.getExpandedItemCount()) .filter(i -> tree.getTreeItem(i).getValue() instanceof Tour) .findFirst() .ifPresent(selectionModel::select); } @Override public void selectLast() { IntStream.iterate(tree.getExpandedItemCount() - 1, i -> i - 1) .limit(tree.getExpandedItemCount()) .filter(i -> tree.getTreeItem(i).getValue() instanceof Tour) .findFirst() .ifPresent(selectionModel::select); } @Override public void clearAndSelect(int index) { int toSelect = index ; int direction = selectionModel.getSelectedIndex() < index ? 1 : -1 ; while (toSelect >= 0 && toSelect < tree.getExpandedItemCount() && ! (tree.getTreeItem(toSelect).getValue() instanceof Tour)) { toSelect = toSelect + direction ; } if (toSelect >= 0 && toSelect < tree.getExpandedItemCount()) { selectionModel.clearAndSelect(toSelect); } } @Override public void select(int index) { int toSelect = index ; int direction = selectionModel.getSelectedIndex() < index ? 1 : -1 ; while (toSelect >= 0 && toSelect < tree.getExpandedItemCount() && ! (tree.getTreeItem(toSelect).getValue() instanceof Tour)) { toSelect = toSelect + direction ; } if (toSelect >= 0 && toSelect < tree.getExpandedItemCount()) { selectionModel.select(toSelect); } } @Override public void select(TreeItem<Object> obj) { if (obj.getValue() instanceof Tour) { selectionModel.select(obj); } } @Override public void clearSelection(int index) { selectionModel.clearSelection(index); } @Override public void clearSelection() { selectionModel.clearSelection(); } @Override public boolean isSelected(int index) { return selectionModel.isSelected(index); } @Override public boolean isEmpty() { return selectionModel.isEmpty(); } @Override public void selectPrevious() { int current = selectionModel.getSelectedIndex() ; if (current > 0) { IntStream.iterate(current - 1, i -> i - 1).limit(current) .filter(i -> tree.getTreeItem(i).getValue() instanceof Tour) .findFirst() .ifPresent(selectionModel::select); } } @Override public void selectNext() { int current = selectionModel.getSelectedIndex() ; if (current < tree.getExpandedItemCount() - 1) { IntStream.range(current + 1, tree.getExpandedItemCount()) .filter(i -> tree.getTreeItem(i).getValue() instanceof Tour) .findFirst() .ifPresent(selectionModel::select); } } } public static class Tour { private final String name ; public Tour(String name) { this.name = name ; } public String getName() { return name ; } @Override public String toString() { return getName(); } } public static class Delivery { private final String name; public Delivery(String name) { this.name = name; } public String getName() { return name; } @Override public String toString() { return getName(); } } public static void main(String[] args) { launch(args); }} 这篇关于TreeView-不允许选择某些TreeItem的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!
09-18 21:13