Как сохранить постоянную позицию неуправляемого узла при изменении его ширины / высоты - PullRequest
0 голосов
/ 01 апреля 2019

В JavaFX как сохранить местоположение (координаты x, y) неуправляемого узла одинаковым при изменении ширины / высоты узла?

Узел неуправляем и размечен с помощью: resizeRelocate. Это работает хорошо, но иногда узел меняет высоту или ширину, и я хотел бы сохранить текущие координаты x, y. то есть узел изменяет размер, но не перемещается в пределах сцены.

Я попытался прослушать свойство boundsInLocal и проверить наличие различий в значениях minY, но узел все еще движется, и вызов resizeRelocate из слушателя boundsInLocal запускает другое обновление boundsInLocal.

Как лучше всего изменить размер и переместить узел так, чтобы я сохранял координаты x, y, но мог изменять ширину / высоту?

Вот пример:

import javafx.scene.*;
import javafx.scene.layout.*;
import javafx.scene.control.*;
import javafx.stage.*;
import javafx.application.*;

public class SizeTest extends Application
{

    public static void main (String[] args)
    {

        Application.launch (args);

    }

    @Override
    public void start (Stage stage)
    {

        try
        {

            VBox b = new VBox ();
            VBox other = new VBox ();
            other.setManaged (false);
            other.setPrefWidth (100);
            other.setStyle ("-fx-border-width: 2px; -fx-border-color: red; -fx-padding: 5px;");

            b.getChildren ().add (other);

            VBox another = new VBox ();
            another.setPrefWidth (50);
            another.setMinHeight (50);
            another.setPrefHeight (50);
            another.setStyle ("-fx-background-color: blue;");

            Button but = new Button ("Push Me");
            but.setOnAction (ev ->
            {

                Button abut = new Button ("Another one");
                other.getChildren ().add (abut);

            });

            other.getChildren ().addAll (another, but);

            other.boundsInLocalProperty ().addListener ((p, oldv, newv) ->
            {

                double h = other.prefHeight (other.getPrefWidth ());

                other.resizeRelocate (other.getBoundsInParent ().getMinX (),
                                      other.getBoundsInParent ().getMinY (),
                                      other.getBoundsInParent ().getWidth (),
                                      h);

            });

            Scene sc = new Scene (b);
            stage.setScene (sc);
            stage.sizeToScene ();
            stage.show ();

            Platform.runLater (() ->
            {

                double h = other.prefHeight (other.getPrefWidth ());

                other.resizeRelocate (100,
                                      100,
                                      other.getPrefWidth (),
                                      h);

            });

        } catch (Exception e) {

            e.printStackTrace ();

        }

    }

}

Когда вы нажимаете кнопку «Push Me», в контейнер добавляется еще одна кнопка, которая затем переполняется. Я бы хотел, чтобы «другой» контейнер вместо этого изменил свой размер до желаемого, но сохранил свои координаты x, y.

Слушатель для свойства boundsInLocal делает это, но вы заметите скачок в положении и неправильный размер. Удаление размера слушателя и правильное расположение узла, но добавление новой кнопки переполняет контейнер.

На данный момент я думаю о создании собственного менеджера компоновки для этого поведения.

1 Ответ

0 голосов
/ 08 апреля 2019

Мое окончательное решение для этого было использовать javafx.scene.layout.Pane.В данном случае я использовал несколько всплывающих окон над содержимым.Я использовал StackPane с «всплывающей панелью», являющейся верхним уровнем с прозрачным фоном.«Всплывающие окна» добавляются в панель и располагаются с помощью Node.relocate (x, y).Панель обрабатывает размеры и будет держать всплывающее окно с указанными координатами x, y.Панель сохраняет всплывающее окно в своем предпочтительном размере, поэтому ручные изменения размеров должны быть выполнены с помощью методов setPref *.

Добавление: пока работает вышеуказанный метод, потому что панель всплывающих окон будет родным для других дочерних элементов StackPane.тогда события не доставляются на «более низкие уровни», т. е. все, что находится под всплывающей панелью.

Чтобы обойти это, я добавил панель контента (нижний уровень) на панель, а затем привязал панель контента.pref width / height в соответствии с размером панели.

т.е.

    this.popupPane = new Pane ();

    this.contentPane = new SplitPane ();
    this.contentPane.prefWidthProperty ().bind (this.popupPane.widthProperty ());
    this.contentPane.prefHeightProperty ().bind (this.popupPane.heightProperty ());
    this.popupPane.getChildren ().add (this.contentPane);
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...