Границы расположения группы и невидимых элементов в JavaFX - PullRequest
0 голосов
/ 06 ноября 2019

У меня есть несколько узлов в группе, видимость которых я хотел бы контролировать с помощью 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, minY:-3.0, minZ:0.0, width:16.0, height:16.0, depth:0.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, 0.0, 3); // radius is 3
        Circle c2 = new Circle(10.0, 10.0, 3);

        Circle c3 = new Circle(20.0, 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);
    }
}

Теперь, каждый раз, когда вы устанавливаете флажок, появляются не только 2 из 4 кружков, но вы также видите, что границы макета группы меняются. Проблема в том, что мне нужно все время знать границы макета, как будто все группы были видны. Я не могу сохранить значение границ, когда они все видимы, потому что для простоты я включил здесь только 4 круга, тогда как в реальном приложении они исчисляются тысячами, и они также перемещаются, когда их не видно, а также есть другие объектык ним привязаны различные размеры, что может еще больше расширить границы макета основной группы.

1 Ответ

0 голосов
/ 06 ноября 2019

Обновленное решение.

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());
        });
    }
}

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...