当前位置: 代码迷 >> java >> JavaFX 8:如何能够调整窗口(舞台)的大小,但将内部元素保持在其位置上?
  详细解决方案

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

热度:91   发布时间:2023-08-02 10:28:02.0

我有一个项目,其中有2个文本区域和几个按钮。 根窗格是AnchorPane。 将窗口调整为较小的窗口时,所有元素开始重叠。 哪些方法可以解决此问题? (忽略我的锚板的名字,我很懒惰)

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

您正在硬编码控件的位置和大小。 这意味着控件无法响应其父节点大小的更改。

通常,您不应指定任何高度或宽度。 控件都具有默认的首选大小,并且所有布局都遵循这些默认大小。 布局还决定了如何根据用户调整窗口大小来调整子节点的大小。

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

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

您可能希望将输入框和“发送”按钮放在单独的子边框BorderPane中,并以输入框为中心节点,因为当用户调整窗口大小时,您希望输入框在水平方向上伸缩。

因此,总结一下:

  • SplitPane中的用户列表和消息区域
  • BorderPane中的typebox和Send按钮
  • 父BorderPane,中间有用户列表/消息部分,底部是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的首选列数。

各种布局的工作情况都有据可查。 我建议在阅读有关它们的信息。

(我猜用户列表应该是ListView,而不是TextArea,因为典型的聊天程序允许选择一个或多个用户。而且我怀疑您的黑色Rectangle和send_text Label旨在表示禁用的Button。)

使用除“锚定窗格”以外的其他窗格。 用于绝对定位。 尝试使用堆栈窗格或简单的VBox。

  相关解决方案