是否有一种简单的方法来检查 FlowPane 内是否有包装元素或确定元素包装的索引?
最佳答案
我不知道它是否符合“简单”的条件,但您可以检查每个子项的 boundsInParent
并将其与第一个子项进行比较。对于水平 FlowPane
这应该有效:
private List<Node> findWrapped(FlowPane flow) {
List<Node> wrapped = new ArrayList<>();
if (flow.getChildren().size() == 0) {
return wrapped ;
}
double y = flow.getChildren().get(0).getBoundsInParent().getMaxY();
for (Node child : flow.getChildren()) {
if (child.getBoundsInParent().getMinY() >= y) {
wrapped.add(child);
}
}
return wrapped ;
}
SSCCE:
import java.util.ArrayList;
import java.util.List;
import javafx.application.Application;
import javafx.scene.Node;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.Label;
import javafx.scene.layout.BorderPane;
import javafx.scene.layout.FlowPane;
import javafx.scene.layout.Pane;
import javafx.scene.layout.StackPane;
import javafx.stage.Stage;
public class FlowPaneWrappedNodes extends Application {
@Override
public void start(Stage primaryStage) {
FlowPane flow = new FlowPane();
for (int i = 1 ; i <= 15; i++) {
flow.getChildren().add(createPane(i));
}
Button button = new Button("Find wrapped");
button.setOnAction(e ->
findWrapped(flow).stream().map(Node::getId).forEach(System.out::println));
BorderPane root = new BorderPane(flow, null, null, button, null);
Scene scene = new Scene(root, 600, 600);
primaryStage.setScene(scene);
primaryStage.show();
}
private List<Node> findWrapped(FlowPane flow) {
List<Node> wrapped = new ArrayList<>();
if (flow.getChildren().size() == 0) {
return wrapped ;
}
double y = flow.getChildren().get(0).getBoundsInParent().getMaxY();
for (Node child : flow.getChildren()) {
if (child.getBoundsInParent().getMinY() >= y) {
wrapped.add(child);
}
}
return wrapped ;
}
private Pane createPane(int id) {
Pane pane = new StackPane();
pane.setMinSize(50, 50);
pane.setId("Pane "+id);
Label label = new Label(Integer.toString(id));
pane.getChildren().add(label);
return pane ;
}
public static void main(String[] args) {
launch(args);
}
}
对于垂直流 Pane ,您可以执行类似的操作,比较边界的 x
值而不是 y
。
更新:
自动重新计算有点棘手。您基本上需要观察 FlowPane 的子列表(以防添加或删除新节点),然后观察流 Pane 中每个节点的边界。您可以使用如下代码来完成此操作:
FlowPane flow = new FlowPane();
ListView<Node> wrappedNodeView = new ListView<>();
ChangeListener<Bounds> boundsListener = (obs, oldBounds, newBounds) ->
wrappedNodeView.getItems().setAll(findWrapped(flow));
flow.getChildren().addListener((Change<? extends Node> c) -> {
while (c.next()) {
if (c.wasAdded()) {
c.getAddedSubList().forEach(node -> node.boundsInParentProperty().addListener(boundsListener));
}
if (c.wasRemoved()) {
c.getRemoved().forEach(node -> node.boundsInParentProperty().removeListener(boundsListener));
}
}
wrappedNodeView.getItems().setAll(findWrapped(flow));
});
(这将创建一个 ListView ,其中显示所有“包装”节点。显然,您可以根据需要更新列表或任何内容。)
这里它被内置到之前的 SSCCE 中:
import javafx.application.Application;
import javafx.beans.value.ChangeListener;
import javafx.collections.FXCollections;
import javafx.collections.ListChangeListener.Change;
import javafx.collections.ObservableList;
import javafx.geometry.Bounds;
import javafx.scene.Node;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.Label;
import javafx.scene.control.ListCell;
import javafx.scene.control.ListView;
import javafx.scene.layout.BorderPane;
import javafx.scene.layout.FlowPane;
import javafx.scene.layout.Pane;
import javafx.scene.layout.StackPane;
import javafx.stage.Stage;
public class FlowPaneWrappedNodes extends Application {
@Override
public void start(Stage primaryStage) {
FlowPane flow = new FlowPane();
ListView<Node> wrappedNodeView = new ListView<>();
ChangeListener<Bounds> boundsListener = (obs, oldBounds, newBounds) ->
wrappedNodeView.getItems().setAll(findWrapped(flow));
flow.getChildren().addListener((Change<? extends Node> c) -> {
while (c.next()) {
if (c.wasAdded()) {
c.getAddedSubList().forEach(node -> node.boundsInParentProperty().addListener(boundsListener));
}
if (c.wasRemoved()) {
c.getRemoved().forEach(node -> node.boundsInParentProperty().removeListener(boundsListener));
}
}
wrappedNodeView.getItems().setAll(findWrapped(flow));
});
wrappedNodeView.setCellFactory(lv -> new ListCell<Node>() {
@Override
public void updateItem(Node item, boolean empty) {
super.updateItem(item, empty);
if (empty) {
setText("");
} else {
setText(item.getId());
}
}
});
Button button = new Button("Add pane");
button.setOnAction(e ->
flow.getChildren().add(createPane(flow.getChildren().size()+1)));
BorderPane root = new BorderPane(flow, null, wrappedNodeView, button, null);
Scene scene = new Scene(root, 600, 600);
primaryStage.setScene(scene);
primaryStage.show();
}
private ObservableList<Node> findWrapped(FlowPane flow) {
ObservableList<Node> wrapped = FXCollections.observableArrayList();
if (flow.getChildren().size() == 0) {
return wrapped ;
}
double y = flow.getChildren().get(0).getBoundsInParent().getMaxY();
for (Node child : flow.getChildren()) {
if (child.getBoundsInParent().getMinY() >= y) {
wrapped.add(child);
}
}
return wrapped ;
}
private Pane createPane(int id) {
Pane pane = new StackPane();
pane.setMinSize(50, 50);
pane.setId("Pane "+id);
Label label = new Label(Integer.toString(id));
pane.getChildren().add(label);
return pane ;
}
public static void main(String[] args) {
launch(args);
}
}
关于java - 检查 JavaFX-FlowPane 中包装的元素,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33456168/