我正在使用BorderPane在JavaFX中实现布局。
假设BorderPane的maxPrefWidth设置为1000。在左窗格中有一个按钮,在右窗格中有一个按钮。在中央窗格中,还有另一个大小未知的按钮。
有没有办法告诉左右窗格自动(水平)增长直到中心节点被击中?
答案 0 :(得分:1)
BorderPane
通过设计扩展了中间区域您的意图与BorderPane
的设计意图不符。
引用Javadoc:
顶部和底部子项将被调整为其首选高度,并扩展边框窗格的宽度。左侧和右侧的子级将被调整为其首选宽度,并在顶部和底部节点之间扩展长度。中心节点将被调整大小以填充中间的可用空间。任何位置都可以为空。
这意味着:
想象一下,中间是一个盒子,里面有一个强人,可以上下推,推。
对于许多商务应用程序来说,这种逻辑通常非常方便。外部区域通常用于navigation,breadcrumbs,menu bar,tool bar,status bar等。然后,内部区域将保留感兴趣的主要内容。在这种用法下,仅将必要的空间分配给外部区域,而将大部分空间分配给内部内容区域是有意义的。
例如,这是一个使用JavaFX 14的完整示例应用程序。
在此示例应用程序的中心区域,我们放置了一个包含单个按钮的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
设置为{{3的同时,使用ColumnConstraints
}和Priority.ALWAYS
放在左侧和右侧的单元格中。
这是一个完整的示例应用程序。
我们在单行HBox
的每个单元格中放置一个按钮,每个按钮嵌套在Priority.SOMETIMES
GridPane
中。颜色使此处显示的上浆行为更加生动。另外,您可以放下彩色的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像素的剩余空间。我们将窗口(colored)设置为1,000像素,并将中间部分的宽度固定为500像素。剩下500像素要分配。左右单元格都设置为相同的优先级,因此它们在它们之间平均分配了空间:500/2 = 250像素。
如果用户将窗口的宽度缩小到600像素,则左侧和右侧的单元格将分别为50像素:600-500 = 100,100 / 2 = 50像素。
答案 1 :(得分:1)
通常,我建议您发布代码,而不要尝试描述它。例如,此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();
}