JavaFX 8:如何能够重新调整 window(舞台)的大小但将内部元素保持在其位置?

JavaFX 8: How to be able to re-size window (stage) but keep inner elements at their positions?

我有一个包含 2 个文本区域和几个按钮的项目。根窗格是一个 AnchorPane。当将 window 调整为更小的 window 时,所有元素开始重叠。什么方法可以解决这个问题? (忽略我锚窗格的名字,我懒了)

    AnchorPane borderpane = new AnchorPane ();

    TextArea user_list = new TextArea();
    user_list.setPrefSize(150, 400);
    TextArea messages = new TextArea();
    messages.setPrefSize(350, 400);
    TextField typebox = new TextField();
    typebox.setPrefSize(425, 100);

    // put a shape over a text, over a shape
    StackPane send_container = new StackPane();

    Rectangle send_box = new Rectangle(75, 25);
    Label send_text = new Label("Send");

    send_container.getChildren().add(send_box);
    send_container.getChildren().add(send_text);

    AnchorPane.setLeftAnchor(messages, 25.0);
    AnchorPane.setTopAnchor(messages, 10.0);
    AnchorPane.setRightAnchor(user_list, 25.0);
    AnchorPane.setTopAnchor(user_list, 10.0);

    AnchorPane.setBottomAnchor(typebox, 25.0); 
    AnchorPane.setLeftAnchor(typebox, 25.0); 
    AnchorPane.setBottomAnchor(send_container, 25.0); 
    AnchorPane.setRightAnchor(send_container, 25.0); 
    borderpane.getChildren().addAll(messages, user_list, typebox,send_container );


    Scene scene = new Scene(borderpane, 600, 600);
    primaryStage.setMaxHeight(600);
    primaryStage.setMaxWidth(600);

    primaryStage.setScene(scene); 
    primaryStage.setTitle("Welcome");
    scene.getStylesheets().add(LoginWindow.class.getResource("Login.css").toExternalForm());
    primaryStage.show();

使用锚定窗格以外的窗格。是为了绝对定位。尝试堆栈窗格或简单的 VBox。

您正在对控件的位置和大小进行硬编码。这意味着控件无法响应其父节点大小的变化。

通常,您不应指定任何高度或宽度。控件都有默认的首选尺寸,所有布局都遵循这些尺寸。布局还决定如何调整子节点的大小以响应用户对 window.

的大小调整。

通常,window 的布局需要分解为子布局。在您的情况下,您希望一个部分始终调整大小以填充 window(用户列表和消息部分),而另一个部分位于底部(类型框和发送按钮)。 BorderPane 是理想的选择,因为它的中心节点总是填充它。因此,此主 BorderPane 的中心将包含用户列表和消息区域,而此 BorderPane 的底部将包含类型框和“发送”按钮。

您可能希望用户能够水平调整用户列表和消息的大小,所以我将它们放在一个 SplitPane 中,并使该 SpiltPane 成为主 BorderPane 的中心。

您可能希望打字框和发送按钮位于单独的子 BorderPane 中,以打字框为中心节点,因为您希望打字框在用户调整大小时水平拉伸和收缩 window.

所以,总结一下:

  • SplitPane 中的用户列表和消息区域
  • BorderPane 中的类型框和发送按钮
  • 父 BorderPane,用户 list/message 部分在中间,typebox/Send 部分在底部

这个代码其实很短:

ListView user_list = new ListView();

TextArea messages = new TextArea();
messages.setPrefRowCount(12);
messages.setPrefColumnCount(30);

TextField typebox = new TextField();
typebox.setPrefColumnCount(30);

Button send_text = new Button("Send");
send_text.disableProperty().bind(
    typebox.lengthProperty().lessThan(1));

SplitPane top = new SplitPane(user_list, messages);
top.setDividerPosition(0, 1/3.0);

BorderPane bottom = new BorderPane();
bottom.setCenter(typebox);
bottom.setRight(send_text);
BorderPane.setMargin(typebox, new Insets(0, 12, 0, 0));

BorderPane main = new BorderPane();
main.setCenter(top);
main.setBottom(bottom);
BorderPane.setMargin(bottom, new Insets(12));

Scene scene = new Scene(main);

primaryStage.setScene(scene); 
primaryStage.setTitle("Welcome");
scene.getStylesheets().add(LoginWindow.class.getResource("Login.css").toExternalForm());
primaryStage.show();

请注意,没有硬编码的尺寸或坐标(Insets 对象定义的边距除外)。每个控件都有一个基于其属性的首选大小,例如 TextField 的首选列数。

各种布局的工作原理都有很好的记录。我建议在 javafx.scene.layout package.

中阅读有关它们的信息

(我猜用户列表应该是 ListView,而不是 TextArea,因为典型的聊天程序允许选择一个或多个用户。我怀疑你的黑色矩形和 send_text 标签是为了代表一个禁用的按钮。)