在使用JavaFX时,我遇到了一个让我难过的布局问题。
我一直在努力寻找一种方法来创建一个可以调整大小的容器,如果容器大于内容,则会将任何内容置于中心,或者如果容器小于内容,则启用滚动条。 对于我的特定应用程序,我希望能够在整个UI上放置“加载”叠加层,因此使用了以下Pane
s的组合:
ScrollPane [yellow border] ->
StackPane [magenta] ->
(content Pane [cyan]), (loading overlay Pane [green])
下面的代码是我所管理的最接近的代码片段,而不依赖于在Java中硬编码的丑陋黑客(理想情况下,这应该在FXML或CSS中完成,以保持布局与代码的分离)。
此代码生成的视图是:
内容(青色轮廓)居中,但看起来StackPane
(洋红色)正在扩展到ScrollPane
宽度的大小,而不是它的视口宽度,强制ScrollPane
始终显示滚动条。 StackPane
的宽度 绑定到ScrollPane
,所以这并不特别令人惊讶,但这是我能想到的最好的。
当窗口小于内容时,设置 按需要工作,至少(我不担心在这种情况下居中):
问题是,如何实现我想要的布局:在可调整大小的窗口中居中的内容,如果需要可以滚动,只使用FXML(和推送的CSS)。
以下是代码段:
Main.java:
import javafx.application.Application;
import javafx.fxml.FXMLLoader;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.stage.Stage;
import java.io.IOException;
public class Main extends Application {
@Override
public void start(final Stage stage) throws IOException {
FXMLLoader templateLoader = new FXMLLoader();
templateLoader.setLocation(getClass().getResource("/test.fxml"));
Parent sceneRoot = templateLoader.load();
TestController controller = templateLoader.getController();
Scene scene = new Scene(sceneRoot, 600, 600);
stage.setScene(scene);
stage.show();
}
public static void main(String[] args) throws IOException {
Main.launch(args);
}
}
TestController.java:
import javafx.fxml.FXML;
import javafx.fxml.Initializable;
import javafx.scene.control.ScrollPane;
import javafx.scene.layout.StackPane;
import java.net.URL;
import java.util.ResourceBundle;
public class TestController implements Initializable {
@FXML
private ScrollPane scroll;
@FXML
private StackPane stack;
@Override
public void initialize(URL location, ResourceBundle resources) {
}
}
test.fxml:
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.scene.layout.StackPane?>
<?import javafx.scene.layout.GridPane?>
<?import javafx.scene.text.Text?>
<?import javafx.scene.control.ScrollPane?>
<?import javafx.scene.control.ProgressIndicator?>
<ScrollPane xmlns:fx="http://javafx.com/fxml/1" xmlns="http://javafx.com/javafx/8.0.101"
fx:controller="TestController"
fx:id="scroll"
style="-fx-border-color: yellow">
<StackPane fx:id="stack" prefWidth="${scroll.width}"
prefHeight="${scroll.height}" style="-fx-border-color: magenta">
<GridPane alignment="CENTER" style="-fx-border-color: cyan"
minWidth="200" maxWidth="200" minHeight="200" maxHeight="200">
<!-- some dummy elements to populate the gridpane... -->
<Text text="text 1" GridPane.columnIndex="0" GridPane.rowIndex="0" />
<Text text="text 2" GridPane.columnIndex="1" GridPane.rowIndex="0" />
<Text text="text 3" GridPane.columnIndex="1" GridPane.rowIndex="1" />
</GridPane>
<ProgressIndicator minWidth="70" maxWidth="70"
minHeight="70" maxHeight="70" style="-fx-border-color: lime"/>
</StackPane>
</ScrollPane>