在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属性的侦听器可以做到这一点,但是您会注意到位置跳动和大小不正确。删除侦听器的大小并正确放置节点,但是添加新按钮会使容器溢出。
目前,我正在考虑为此行为创建自己的布局管理器。
答案 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);