宽度/高度变化时如何固定非托管节点的位置

时间:2019-04-01 03:30:35

标签: javafx

在JavaFX中,当节点的宽度/高度改变时,如何保持非托管节点的位置(x,y坐标)相同?

该节点不受管理,并且使用以下命令进行布局:resizeRelocate。这工作得很好,但有时节点会更改高度或宽度,我想保持当前的x,y坐标。即节点会更改大小,但不会在场景内移动。

我曾尝试收听boundsInLocal属性并检查minY值之间的差异,但该节点仍在移动,并从boundsInLocal侦听器中调用resizeRelocate会触发另一个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 :(得分:0)

我对此的最终解决方案是使用javafx.scene.layout.Pane。我的用例是在内容上方显示一些弹出窗口。我使用了StackPane,“弹出窗格”是具有透明背景的顶层。将“弹出窗口”添加到窗格中,并使用Node.relocate(x,y)进行定位。窗格处理大小调整,并将弹出窗口保持在指定的x,y坐标处。窗格将弹出窗口保持在其首选大小,因此应通过setPref *方法手动更改大小。

附录:在上述方法有效的同时,由于弹出窗格将是StackPane其他子级的同级,因此事件不会传递到“较低级别”,即弹出窗格下方的任何内容。

要解决此问题,我将内容窗格(较低级别)添加到了窗格中,然后将内容窗格的首选宽度/高度与窗格的大小绑定在一起。

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