我試圖在JavaFX中實現TreeView
的搜索功能。我想在用戶點擊回車鍵時突出顯示所有匹配項。所以我在TreeItem
和我的TreeCell
s updateItem
上加了一個boolean isHighlighted
,我檢查是否項isHighlighted
,如果是這樣我申請了某個CSS。一切工作正常的項目/細胞搜索時不可見 - 當我滾動到他們,他們正確地突出顯示。問題是:如何在搜索時「重新繪製」可見的TreeCell,以便它們反映它們的項目isHighlighted
?我的控制器目前沒有任何參考TreeCells
TreeView
創建。JavaFX:如何突出顯示TreeView中的某些項目
0
A
回答
1
此答案基於this one,但適用於TreeView
而不是TableView
,並更新爲使用JavaFX 8功能(極大地減少了所需的代碼量)。
對此的一個策略是維護與搜索相匹配的ObservableSet
TreeItems
(這對於您可能想要的其他功能有時會有用)。使用CSS PseudoClass
和外部CSS文件來突出顯示所需的單元格。您可以在單元格工廠中創建一個BooleanBinding
,該單元工廠綁定到單元格的treeItemProperty
和ObservableSet
,如果集合包含單元格的當前樹項目,則評估爲true
。然後,只需向綁定註冊一個偵聽器,並在更改時更新單元的僞類狀態。
這是一個SSCCE。它包含一棵樹,其項目是Integer
-已評估。當您在搜索框中輸入內容時,它將更新搜索,匹配其值爲輸入值的倍數的搜索。
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Random;
import java.util.Set;
import javafx.application.Application;
import javafx.beans.binding.Bindings;
import javafx.beans.binding.BooleanBinding;
import javafx.collections.FXCollections;
import javafx.collections.ObservableSet;
import javafx.css.PseudoClass;
import javafx.geometry.Insets;
import javafx.scene.Scene;
import javafx.scene.control.TextField;
import javafx.scene.control.TextFormatter;
import javafx.scene.control.TreeCell;
import javafx.scene.control.TreeItem;
import javafx.scene.control.TreeView;
import javafx.scene.layout.BorderPane;
import javafx.stage.Stage;
public class TreeWithSearchAndHighlight extends Application {
@Override
public void start(Stage primaryStage) {
TreeView<Integer> tree = new TreeView<>(createRandomTree(100));
// keep track of items that match our search:
ObservableSet<TreeItem<Integer>> searchMatches = FXCollections.observableSet(new HashSet<>());
// cell factory returns an instance of TreeCell implementation defined below.
// pass the cell implementation a reference to the set of search matches
tree.setCellFactory(tv -> new SearchHighlightingTreeCell(searchMatches));
// search text field:
TextField textField = new TextField();
// allow only numeric input:
textField.setTextFormatter(new TextFormatter<Integer>(change ->
change.getControlNewText().matches("\\d*")
? change
: null));
// when the text changes, update the search matches:
textField.textProperty().addListener((obs, oldText, newText) -> {
// clear search:
searchMatches.clear();
// if no text, or 0, just exit:
if (newText.isEmpty()) {
return ;
}
int searchValue = Integer.parseInt(newText);
if (searchValue == 0) {
return ;
}
// search for matching nodes and put them in searchMatches:
Set<TreeItem<Integer>> matches = new HashSet<>();
searchMatchingItems(tree.getRoot(), matches, searchValue);
searchMatches.addAll(matches);
});
BorderPane root = new BorderPane(tree, textField, null, null, null);
BorderPane.setMargin(textField, new Insets(5));
BorderPane.setMargin(tree, new Insets(5));
Scene scene = new Scene(root, 600, 600);
// stylesheet sets style for cells matching search by using the selector
// .tree-cell:search-match
// (specified in the initalization of the Pseudoclass at the top of the code)
scene.getStylesheets().add("tree-highlight-search.css");
primaryStage.setScene(scene);
primaryStage.show();
}
// find all tree items whose value is a multiple of the search value:
private void searchMatchingItems(TreeItem<Integer> searchNode, Set<TreeItem<Integer>> matches, int searchValue) {
if (searchNode.getValue() % searchValue == 0) {
matches.add(searchNode);
}
for (TreeItem<Integer> child : searchNode.getChildren()) {
searchMatchingItems(child, matches, searchValue);
}
}
// build a random tree with numNodes nodes (all nodes expanded):
private TreeItem<Integer> createRandomTree(int numNodes) {
List<TreeItem<Integer>> items = new ArrayList<>();
TreeItem<Integer> root = new TreeItem<>(1);
root.setExpanded(true);
items.add(root);
Random rng = new Random();
for (int i = 2 ; i <= numNodes ; i++) {
TreeItem<Integer> item = new TreeItem<>(i);
item.setExpanded(true);
TreeItem<Integer> parent = items.get(rng.nextInt(items.size()));
parent.getChildren().add(item);
items.add(item);
}
return root ;
}
public static class SearchHighlightingTreeCell extends TreeCell<Integer> {
// must keep reference to binding to prevent premature garbage collection:
private BooleanBinding matchesSearch ;
public SearchHighlightingTreeCell(ObservableSet<TreeItem<Integer>> searchMatches) {
// pseudoclass for highlighting state
// css can set style with selector
// .tree-cell:search-match { ... }
PseudoClass searchMatch = PseudoClass.getPseudoClass("search-match");
// initialize binding. Evaluates to true if searchMatches
// contains the current treeItem
// note the binding observes both the treeItemProperty and searchMatches,
// so it updates if either one changes:
matchesSearch = Bindings.createBooleanBinding(() ->
searchMatches.contains(getTreeItem()),
treeItemProperty(), searchMatches);
// update the pseudoclass state if the binding value changes:
matchesSearch.addListener((obs, didMatchSearch, nowMatchesSearch) ->
pseudoClassStateChanged(searchMatch, nowMatchesSearch));
}
// update the text when the item displayed changes:
@Override
protected void updateItem(Integer item, boolean empty) {
super.updateItem(item, empty);
setText(empty ? null : "Item "+item);
}
}
public static void main(String[] args) {
launch(args);
}
}
CSS文件樹亮點,search.css只是必須包含一個風格突出顯示單元:
.tree-cell:search-match {
-fx-background: yellow ;
}
相關問題
- 1. 突出顯示TreeView中的父項目
- 2. Treeview - 突出顯示多個項目
- 3. jquery treeview突出顯示所選項目
- 4. JavaFX Treeview顯示沒有項目
- 5. WPF:突出顯示TreeView項目顯示上下文Meu
- 6. SQL如何在某些條件下突出顯示重複項
- 7. 突出顯示組合框中的某些選項
- 8. 我可以'突出顯示'UIpickerview中的某些選項嗎?
- 9. 如何突出顯示ListView項目
- 10. silverlight combobox - 突出顯示彈出列表中的一些項目
- 11. Solr不突出顯示某些詞
- 12. 如何在TreeView中突出顯示TreeviewItem以顯示狀態?
- 13. WPF突出顯示項目
- 14. jquery treeview只突出顯示當前項目
- 15. 如何使用jQuery突出顯示HTML選擇中的某些選項
- 16. 如何使用Powershell在Excel列中突出顯示某些值
- 17. RecyclerView中突出顯示的大項目
- 18. 在ListView中突出顯示項目
- 19. 如何防止某些列在選擇行時突出顯示
- 20. ArcGis Engine如何突出顯示某些功能/形狀?
- 21. :如何用jQuery突出顯示某些單詞
- 22. 點擊時如何突出顯示某些元素?
- 23. 如何突出顯示WPF treeview中的搜索結果?
- 24. Android:突出顯示setSelecton上的項目
- 25. 如何選擇或突出顯示QTreeWidget中的所有項目?
- 26. 如何突出顯示ListView中的選定項目?
- 27. 如何突出顯示Recycler視圖中的選定項目
- 28. 如何使用WPF突出顯示組合框中的項目?
- 29. 如何突出顯示sencha ExtJS列表中的項目?
- 30. 如何設置畫廊中的突出顯示項目android
這工作近乎完美。我不得不更換一個事件處理,這樣它會突出TreeCells:? 'Platform.runLater(() - > { 事件處理程序<超表示ScrollEvent> E = myTreeView.getChildrenUnmodifiable()得到(0).getOnScroll() ; myTreeView.getChildrenUnmodifiable()得到(0).setOnScroll。((事件) - > { e.handle(事件); 搜索(s.SearchTextField.getText()); } }) ; });' –
spilot
無論如何,非常感謝。您的解決方案不僅工作得很好,而且還很優雅。 – spilot
我真的不明白爲什麼你需要額外的黑客,或者它真的做了什麼。只要您在進行新搜索時更新'ObservableSet',樹就會自動更新。 –