簡體   English   中英

JavaFX BorderPane 布局(拉伸左右窗格)

[英]JavaFX BorderPane Layout (Stretch Left and Right Pane)

我正在使用 BorderPane 在 JavaFX 中實現布局。

假設 BorderPane 的 maxPrefWidth 設置為 1000。左窗格中有一個按鈕,右窗格中有一個按鈕。 在中心窗格中,還有另一個大小未知的按鈕。

  • 如果:中間元素的寬度是500,那么左右節點的寬度應該是250。
  • 如果:中間元素的寬度是600,那么左右節點的寬度應該是200。

有沒有辦法告訴左右窗格自動增長(水平)直到中心節點被擊中?

BorderPane通過設計擴展了中間區域

您的意圖與BorderPane的設計意圖不符。

引用 Javadoc:

頂部和底部的孩子將被調整到他們喜歡的高度並擴展邊框窗格的寬度。 左右子節點將被調整為其首選寬度並延長頂部和底部節點之間的長度。 並且中心節點將調整大小以填充中間的可用空間。 任何位置都可以是 null。

這表示:

  • 該中心擴展以占用所有額外的空間。
  • 頂部和底部采用最大寬度和它們的首選高度。
  • 左側和右側區域采用其首選寬度和最大高度。

把中間想象成一個盒子,里面有一個強人向上、向下和向外推。

BorderPane 的五個區域的圖表,顯示了中心如何擴展而外部區域折疊其寬度或高度

對於許多業務應用程序來說,這種邏輯通常非常方便。 外部區域通常用於導航面包屑菜單欄工具欄狀態欄等。 內部區域則保存主要的興趣內容。 鑒於這種用法,只為外部區域分配必要的空間,而將大部分空間分配給內部內容區域是有意義的。

例如,這是一個使用 JavaFX 14 的完整示例應用程序。

使用 BorderPane 布局的示例 JavaFX 應用程序的屏幕截圖,以顯示彩色中心區域如何增長以占用所有額外空間

在這個示例應用程序的中心區域,我們放置了一個包含單個按鈕的HBox布局。 我們將該布局的背景顏色設置為cornflowerblue藍色,以顯示中心區域的內容如何擴展以占用所有額外空間。

package work.basil.example;

import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.Label;
import javafx.scene.control.ToolBar;
import javafx.scene.layout.BorderPane;
import javafx.scene.layout.HBox;
import javafx.stage.Stage;

import java.time.ZonedDateTime;

/**
 * JavaFX App
 */
public class App extends Application
{

    @Override
    public void start ( Stage stage )
    {
        // Widgets
        ToolBar toolBar = new ToolBar();
        Button button = new Button( "Click Me" );
        toolBar.getItems().add( button );

        Button buttonLeft = new Button( "Left" );
        Button buttonRight = new Button( "Right" );

        HBox appContent = new HBox( new Button( "Bonjour le monde" ) );
        appContent.setStyle( "-fx-background-color: cornflowerblue;" );

        HBox statusBar = new HBox( new Label( "Status goes here. Now: " + ZonedDateTime.now() ) );

        // Arrange
        BorderPane borderPane = new BorderPane();
        borderPane.setTop( toolBar );
        borderPane.setLeft( buttonLeft );
        borderPane.setCenter( appContent );
        borderPane.setRight( buttonRight );
        borderPane.setBottom( statusBar );

        var scene = new Scene( borderPane , 1000 , 1000 );
        stage.setScene( scene );
        stage.show();
    }

    public static void main ( String[] args )
    {
        launch();
    }
}

選擇其他布局

正如對問題的評論,您應該根據您的意圖使用不同的布局管理器。

您也許可以使用HBox 為了最大限度地控制,您需要花一些時間來掌握GridPane

GridPane

你的問題並不完全清楚。 如果您想要的是中心內容的固定寬度為 500 像素,而左側和右側是靈活的,按比例分配任何額外空間,然后使用GridPane將左側的ColumnConstraints設置為Priority.SOMETIMESPriority.ALWAYS和正確的細胞。

這是一個完整的示例應用程序。

我們在單行GridPane的每個單元格中放置一個按鈕,每個按鈕都嵌套在一個彩色HBox中。 colors 戲劇化了此處顯示的大小調整行為。 或者,您可以刪除彩色HBox ,而是調用gridPane.setStyle( "-fx-grid-lines-visible: true;" )來顯示每個單元格周圍的邊框線。

package work.basil.example;

import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.Label;
import javafx.scene.control.ToolBar;
import javafx.scene.layout.*;
import javafx.stage.Stage;

import java.time.ZonedDateTime;

/**
 * JavaFX App
 */
public class App extends Application
{

    @Override
    public void start ( Stage stage )
    {
        // Widgets
        Button buttonLeft = new Button( "Left" );
        HBox left = new HBox( buttonLeft );
        left.setStyle( "-fx-background-color: Salmon;" );

        Button buttonCenter = new Button( "Center" );
        HBox center = new HBox( buttonCenter );
        center.setStyle( "-fx-background-color: CornflowerBlue;" );

        Button buttonRight = new Button( "Right" );
        HBox right = new HBox( buttonRight );
        right.setStyle( "-fx-background-color: MediumSeaGreen;" );

        // GridPane
        GridPane gridPane = new GridPane();
        gridPane.addRow( 0 , left , center , right );  // Add these widgets in first row (annoying zero-based counting means index 0 is row 1).
        gridPane.setStyle( "-fx-grid-lines-visible: true ;" );  // Add lines to the edges of each cell (row/column) in the grid. Useful for learning and debugging. https://docs.oracle.com/javafx/2/api/javafx/scene/doc-files/cssref.html#gridpane

        // Grid constraints
        ColumnConstraints column1 = new ColumnConstraints();
        column1.setHgrow( Priority.SOMETIMES ); // Extra space alloted to this column.

        ColumnConstraints column2 = new ColumnConstraints( 500 ); // Fixed width of 500 pixels.

        ColumnConstraints column3 = new ColumnConstraints();
        column3.setHgrow( Priority.SOMETIMES );// Extra space alloted to this column.

        gridPane.getColumnConstraints().addAll( column1 , column2 , column3 ); // first column gets any extra width

        // Render
        var scene = new Scene( gridPane , 1000 , 150 );
        stage.setScene( scene );
        stage.setTitle( "Example of JavaFX GridPane, by Basil Bourque" );
        stage.show();
    }


    public static void main ( String[] args )
    {
        launch();
    }
}

正在運行的應用程序的屏幕截圖。 請注意左右如何分別獲得 250 像素的剩余空間。 我們將 window ( Stage ) 設置為 1,000 像素,並將中心部分的寬度固定為 500 像素。 剩下 500 個像素要分配。 左右單元格都設置為相同的優先級,因此它們在它們之間平均分配空間:每個 500/2 = 250 像素。

JavaFX 14 應用程序的屏幕截圖顯示了一個 3 列和 1 行的 GridPane,其中左側和右側單元格在中心占用 500 像素寬度后獲得任何額外空間。

如果用戶將 window 的寬度縮小到 600 像素,則左右單元格將分別為 50 像素:600 - 500 = 100、100/2 = 50 像素。

在此處輸入圖像描述

一般來說,我建議發布代碼而不是試圖描述它。 例如,這個mre可以代表您的問題:

import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.layout.BorderPane;
import javafx.scene.layout.Pane;
import javafx.stage.Stage;

public class Main extends Application {
    @Override
    public void start(Stage stage) throws Exception   {

        Button leftBtn = new Button("Left");
        Button centerBtn = new Button("Center");
        centerBtn.widthProperty().addListener((obs, oldValue,newValue)-> {
                //change the logic as needed
                leftBtn.setPrefWidth(newValue.doubleValue() >= 600 ? 200 : 250);
        });
        centerBtn.setPrefSize(600, 0);
        Button rightBtn = new Button("Right");
        Pane root = new BorderPane(centerBtn, null, rightBtn, null, leftBtn);
        root.setPrefSize(1000, 150);
        Scene scene = new Scene(root);
        stage.setScene(scene);
        stage.show();
    }

public static void main(String[] args) {
        launch(args);
    }
}

這也使幫助變得更加容易。 例如,評論中提出的帶有HBox的解決方案只需要對 mre 進行細微更改(將操作框添加到中心按鈕以更改其寬度):

import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.layout.HBox;
import javafx.scene.layout.Pane;
import javafx.scene.layout.Priority;
import javafx.stage.Stage;

public class Main extends Application {

    private static final double MIN = 300, MAX = 700, DELTA = 100;
    private Button centerBtn;
    @Override
    public void start(Stage stage) throws Exception   {

        Button leftBtn = new Button("Left");
        HBox.setHgrow(leftBtn, Priority.NEVER);

        centerBtn = new Button("Click to change width");
        HBox.setHgrow(leftBtn, Priority.NEVER);
        centerBtn.widthProperty().addListener((obs, oldValue,newValue)-> {
            //change the logic as needed
            leftBtn.setPrefWidth(newValue.doubleValue() >= 600 ? 200 : 250);
        });
        centerBtn.setPrefSize(600, 0);
        centerBtn.setOnAction(e-> changeCenterBtnWidth());
        Button rightBtn = new Button("Right");
        HBox.setHgrow(rightBtn, Priority.ALWAYS);
        Pane root = new HBox(leftBtn,centerBtn,rightBtn);
        root.setPrefSize(1000, 150);
        Scene scene = new Scene(root);
        stage.setScene(scene);
        stage.show();
    }

    private void changeCenterBtnWidth() {
        double newWidth = centerBtn.getWidth() +  DELTA;
        newWidth = newWidth < MAX ? newWidth : MIN;
        centerBtn.setPrefWidth(newWidth);
    }

    public static void main(String[] args) {
        launch(args);
    }
}

演示基於GridPane的解決方案只需要一些小改動:

    public void start(Stage stage) throws Exception   {

        Button leftBtn = new Button("Left");

        centerBtn = new Button("Click to change width");
        centerBtn.widthProperty().addListener((obs, oldValue,newValue)-> {
            //change the logic as needed
            leftBtn.setPrefWidth(newValue.doubleValue() >= 600 ? 200 : 250);
        });
        centerBtn.setPrefSize(600, 0);
        centerBtn.setOnAction(e-> changeCenterBtnWidth());
        Button rightBtn = new Button("Right");

        GridPane root = new GridPane();
        root.add(leftBtn,0, 0);
        root.add(centerBtn,1, 0);
        root.add(rightBtn,2, 0);
        root.setPrefSize(1000, 150);
        Scene scene = new Scene(root);
        stage.setScene(scene);
        stage.show();
   }

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM