Im有FlowPane,它包含各种元素。我希望能够使用FilteredList<MyElement>,以便用户能够进行搜索,但是FlowPane只有getChildren()方法。如何过滤FlowPane中显示的节点
发布于 2020-06-16 12:15:06
假设MyElement是Node的子类,您可以简单地
FlowPane flowPane = ... ;
FilteredList<MyElement> someFilteredList = ... ;
Bindings.bindContent(flowPane.getChildren(), someFilteredList)这里是一个非常快速和肮脏的例子,它创建100个以整数值作为文本的标签。文本字段更新筛选列表中的筛选器,以便只显示其值为输入值的倍数的标签。
import javafx.application.Application;
import javafx.beans.binding.Bindings;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.collections.transformation.FilteredList;
import javafx.geometry.Insets;
import javafx.scene.Scene;
import javafx.scene.control.Label;
import javafx.scene.control.TextField;
import javafx.scene.layout.BorderPane;
import javafx.scene.layout.FlowPane;
import javafx.stage.Stage;
/**
* JavaFX App
*/
public class App extends Application {
@Override
public void start(Stage stage) {
FlowPane flow = new FlowPane();
ObservableList<Label> labels = FXCollections.observableArrayList();
for (int i = 1 ; i <= 100 ; i++) {
Label label = new Label(Integer.toString(i));
label.setPadding(new Insets(1,5,0,0));
labels.add(label);
}
FilteredList<Label> filtered = new FilteredList<>(labels);
TextField filter = new TextField();
filter.setTextFormatter(new TextFormatter<String>(change ->
change.getControlNewText().matches("[0-9]*") ? change : null
));
filter.textProperty().addListener((obs, oldFilter, newFilter) -> {
String f = newFilter.trim();
if (f.isEmpty()) {
filtered.setPredicate(l -> true);
} else {
Integer divisor = Integer.parseInt(f);
filtered.setPredicate(label -> Integer.parseInt(label.getText()) % divisor == 0);
}
});
Bindings.bindContent(flow.getChildren(), filtered);
BorderPane root = new BorderPane(flow);
root.setTop(filter);
Scene scene = new Scene(root);
stage.setScene(scene);
stage.show();
}
public static void main(String[] args) {
launch();
}
}发布于 2020-06-16 12:01:15
您只能操作FlowPane子列表的项目。无法设置要处理控制子控件的列表的任何实现。
正如@James_D所提到的,您可以使用Bindings.bindContent。只有当筛选器更改时才更新谓词(或者您可以将其编辑为bind)。
public class Controller {
@FXML
FlowPane flowPane;
@FXML
ComboBox<Class> filterCbx;
FilteredList<Node> filteredList;
@FXML
void initialize() {
// Set of all the controls classes in flow pane children classes
ObservableList<Node> flowChildren = flowPane.getChildren();
filterCbx.getItems().addAll(flowChildren
.stream()
.map(Node::getClass)
.collect(Collectors.toSet()));
// Node will be treated as show all children functionality
filterCbx.getItems().add(Node.class);
filterCbx.setOnAction(this::onFilterChanged);
// Source need to be an another FXCollection, cant use directly flowChildren
filteredList = new FilteredList<Node>(FXCollections.observableArrayList(flowChildren));
Bindings.bindContent(flowChildren, filteredList);
}
private void onFilterChanged(ActionEvent actionEvent) {
ObservableList<Node> flowChildren = flowPane.getChildren();
Class selectedItem = filterCbx.getSelectionModel().getSelectedItem();
// Update predicate on selection change
filteredList.setPredicate(n -> Node.class.equals(selectedItem) || n.getClass().equals(selectedItem));
}
}意见如下:
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.scene.control.*?>
<?import javafx.scene.layout.*?>
<VBox maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity"
prefHeight="400.0"
prefWidth="600.0" xmlns="http://javafx.com/javafx/10.0.2-internal" xmlns:fx="http://javafx.com/fxml/1"
fx:controller="so.q62406187.Controller">
<ComboBox fx:id="filterCbx"/>
<FlowPane fx:id="flowPane">
<Pane prefHeight="200.0" prefWidth="200.0"/>
<Button mnemonicParsing="false" text="Button"/>
<Label text="Label"/>
<ComboBox prefWidth="150.0"/>
<HBox prefHeight="100.0" prefWidth="200.0"/>
<CheckBox mnemonicParsing="false" text="CheckBox"/>
<VBox prefHeight="200.0" prefWidth="100.0"/>
<CheckBox mnemonicParsing="false" text="CheckBox"/>
<Label text="Label"/>
</FlowPane>
</VBox>https://stackoverflow.com/questions/62406187
复制相似问题