组的布局边界和JavaFX中的不可见元素

我在一个组中有多个节点,我想使用visibleProperty()来控制其可见性。我观察到,关闭某个元素的可见性会影响该组的布局范围。重新计算它们,就好像该元素根本不存在,不仅是不可见。有没有办法保持节点的存在,而只是关闭它的可见性,以便调整布局边界,就像整个节点都在那一样?

用于说明问题的示例,假设节点在下面的圆圈中。

        Circle c1 = new Circle(0.0,0.0,3); // radius is 3
        Circle c2 = new Circle(10.0,10.0,3);
        Circle c3 = new Circle(20.0,20.0,3);

        Group g = new Group();

        g.getchildren().addAll(c1,c2,c3);
        Bounds b1 = g.getLayoutBounds();

        c3.visibleProperty().setvalue(false);
        Bounds b2 = g.getLayoutBounds();

b and b2的范围将跨越:

b1 = BoundingBox [minX:-3.0,minY:-3.0,minZ:0.0,width:26.0,height:26.0,depth:0.0,maxX:23.0,maxY:23.0,maxZ:0.0]
b2 = BoundingBox [minX:-3.0,width:16.0,height:16.0,maxX:13.0,maxY:13.0,maxZ:0.0]

边界b2是在关闭圆c3的可见性之后计算的,因此它们相对于原始边界b1会缩小。我希望有一种方法可以将边界扩展到b1,即使该组中的某些元素不可见。

修改 最小的可重现示例:

package sample;

import javafx.application.Application;
import javafx.beans.value.changelistener;
import javafx.beans.value.ObservableValue;
import javafx.geometry.Bounds;
import javafx.scene.Group;
import javafx.scene.Scene;
import javafx.scene.control.CheckBox;
import javafx.scene.layout.HBox;
import javafx.scene.shape.Circle;
import javafx.stage.Stage;

public class Main extends Application {

    @Override
    public void start(Stage primaryStage) throws Exception{

        Circle c1 = new Circle(0.0,3);

        Circle c3 = new Circle(20.0,3); // radius is 3
        Circle c4 = new Circle(30.0,30.0,3);

        Group g1 = new Group();
        Group g2 = new Group();

        g1.getchildren().addAll(c1,c2);
        g2.getchildren().addAll(c3,c4);

        Group main = new Group(g1,g2);

        CheckBox checkBox1 = new CheckBox("Show");
        g2.visibleProperty().bind(checkBox1.selectedProperty());

        Bounds b1 = main.getLayoutBounds();
        System.out.println(b1);

        checkBox1.selectedProperty().addListener(new changelistener<Boolean>() {
            @Override
            public void changed(ObservableValue<? extends Boolean> observableValue,Boolean aBoolean,Boolean t1) {
                System.out.println(main.getLayoutBounds());
            }
        });

        HBox hbox = new HBox(checkBox1,main);

        Scene scene = new Scene(hbox,400,300);

        primaryStage.setTitle("Hello Stackoverflow,are you happy now?");
        primaryStage.setScene(scene);
        primaryStage.show();
    }


    public static void main(String[] args) {
        launch(args);
    }
}

现在,任何时候选择复选框,不仅会显示4个圆圈中的2个,而且您还将看到组的布局范围发生了变化。问题是我需要始终知道布局边界,就像所有组都可见一样。当边界值全部可见时,我无法存储它们的边界值,因为为简单起见,我仅在此处包括4个圆,而在实际应用中,它们以数千为单位,当不可见时它们也在四处移动,并且还有其他对象它们具有不同的大小,这可能会进一步扩大主要组的布局范围。

zcz888 回答:组的布局边界和JavaFX中的不可见元素

更新的解决方案。

import javafx.beans.binding.Bindings;
import javafx.beans.property.BooleanProperty;
import javafx.beans.property.SimpleBooleanProperty;
import javafx.beans.value.ChangeListener;
import javafx.collections.FXCollections;
import javafx.collections.ListChangeListener;
import javafx.collections.ObservableList;
import javafx.scene.Group;
import javafx.scene.paint.Color;
import javafx.scene.paint.Paint;
import javafx.scene.shape.Shape;

public class ShapesGroup extends Group {

    public final BooleanProperty transparentProperty = new SimpleBooleanProperty();

    private final ObservableList<Shape> shapes = FXCollections.observableArrayList();

    public ShapesGroup() {
        Bindings.bindContent(getChildren(),shapes);

        shapes.addListener((ListChangeListener<Shape>) change -> {
            while (change.next()) {
                if (change.wasAdded()) {
                    for (Shape shape : change.getAddedSubList()) {
                        shape.fillProperty().addListener((ChangeListener<Paint>) (observable,oldFill,newFill) -> {
                            transparentProperty.addListener((ChangeListener<Boolean>) (observable1,oldTransparent,newTransparent) -> {
                                if (!newTransparent) {
                                    shape.setFill(oldFill);
                                }
                            });
                        });
                        transparentProperty.addListener((ChangeListener<Boolean>) (observable,oldValue,newValue) -> {
                            if (newValue) {
                                shape.setFill(Color.TRANSPARENT);
                            }
                        });
                    }
                }
            }
        });

    }

    public ObservableList<Shape> getShapes() {
        return shapes;
    }
}
import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.layout.Priority;
import javafx.scene.layout.StackPane;
import javafx.scene.layout.VBox;
import javafx.scene.paint.Color;
import javafx.scene.shape.Circle;
import javafx.scene.shape.Rectangle;
import javafx.stage.Stage;

public class MainApp extends Application {

    public static void main(String[] args) {
        launch(args);
    }

    @Override
    public void start(Stage stage) throws Exception {
        Rectangle rectangle = new Rectangle(40,40,Color.YELLOW);
        Circle circle = new Circle(20,Color.RED);
        ShapesGroup group = new ShapesGroup();
        group.getShapes().addAll(rectangle,circle);

        StackPane stackPane = new StackPane(group);

        Button button = new Button("Switch");
        VBox vBox = new VBox(stackPane,button);
        VBox.setVgrow(stackPane,Priority.ALWAYS);

        Scene scene = new Scene(vBox,400,400);
        stage.setScene(scene);
        stage.show();

        button.setOnAction(event -> {
            group.transparentProperty.set(!group.transparentProperty.get());
        });
    }
}

本文链接:https://www.f2er.com/3151238.html

大家都在问