如何使 JavaFX 控件居中

2022-09-04 06:41:58

更具体地说,为什么我的 JavaFX 控件没有居中?这是两个屏幕截图,第一个是在启动后(我将窗口移动到一个更明显的位置,但尚未调整其大小),第二个是在调整其大小以展示我的问题之后。如果您帮助我确保它在首次显示时(在所有DPI上)大小正确,则可以获得奖励积分:

A small window with the title "Checking", and only a small sliver of content, on top of its own codeThe same scene, but the window now shows the title "Checking for Updates...", its content more apparent, where the components are centered, but not their content.

方便的是,相关代码包含在这些屏幕截图中。如果您仍然需要它作为文本,请转到此处:

private void initJFXPanel(JFXPanel holder)
{
    {
        {
            rootGrid = new GridPane();
            rootGrid.setAlignment(Pos.CENTER);
            rootGrid.setPadding(new Insets(16));
            rootGrid.setHgap(16);
            rootGrid.setVgap(8);
        }

        interior = holder.getScene();
        if (interior == null)
            holder.setScene(interior = new Scene(rootGrid));
        interior.setRoot(rootGrid);

    }
    {
        statusLabel = new Label("Checking for Updates...");
        statusLabel.setAlignment(Pos.CENTER);
        statusLabel.setTextAlignment(TextAlignment.CENTER);
        rootGrid.add(statusLabel, 0, 0);
    }
    {
        progressBar = new ProgressBar();
        progressBar.setProgress(-1);
        progressBar.setPrefWidth(Constants.MAX_WIN_BOUNDS.width / 5d); // 1/5 the width of the screen
        rootGrid.add(progressBar, 0, 1);
    }
    {
        downloadButton = new Button("Get it!");
        downloadButton.setAlignment(Pos.CENTER);
        rootGrid.add(downloadButton, 0, 2);
    }
    holder.setMinimumSize(new Dimension((int)(rootGrid.getPrefWidth() + .5), (int)(rootGrid.getPrefHeight() + .5)));
    setMinimumSize(holder.getMinimumSize());
}

答案 1

溶液

将控件放在 VBox(或其他类似的根布局窗格)中,并将 VBox 对齐方式设置为居中。

布局建议

这是我个人关于从JavaFX中的布局开始的建议(这只是建议,并不适用于每个人,你可以接受它或离开它):

  • 您的窗口以及所有控件和布局将自动调整为其首选大小。
  • 让内置布局管理器和布局系统为您进行尽可能多的计算,您只需提供获得结果所需的最少布局提示即可。
  • 坚持仅使用JavaFX或仅Swing代码,直到您熟悉这两种代码开发风格并且真正需要混合使用它们。
  • 使用 SceneBuilder 工具尝试不同的布局,并熟悉 JavaFX 布局机制。
  • 学习 JavaFX 布局教程
  • 查看有关 JavaFX 布局的演示文稿
  • 若要将舞台居中,请呼叫舞台.centerOnScreen()
  • 请考虑使用 Java 8u40 的内置对话框支持(发布时)。

高 dpi 支持

请参阅以下问题的答案:

基于 FXML 的对话示例代码

update-check

您可以在 SceneBuilder 中加载以下内容以轻松显示它:

<?xml version="1.0" encoding="UTF-8"?>

<?import javafx.geometry.*?>
<?import javafx.scene.control.*?>
<?import java.lang.*?>
<?import javafx.scene.layout.*?>

<VBox alignment="CENTER" maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" spacing="8.0" xmlns="http://javafx.com/javafx/8" xmlns:fx="http://javafx.com/fxml/1">
   <children>
      <Label fx:id="updateStatus" text="Checking for Updates..." />
      <ProgressBar fx:id="updateProgress" prefWidth="200.0" progress="0.0" />
      <Button fx:id="updateAction" mnemonicParsing="false" text="Get it!" />
   </children>
   <padding>
      <Insets bottom="16.0" left="16.0" right="16.0" top="16.0" />
   </padding>
</VBox>

答案 2

调整大小问题

确保要将尺寸添加到您的JFrame

frame.setSize(500, 300);

中心问题

我不确定你是在网格窗格中将帧或JavaFX控件居中,所以我正在为它们添加答案

框架屏幕居中

Dimension dim = Toolkit.getDefaultToolkit().getScreenSize();
frame.setLocation(dim.width/2-frame.getSize().width/2, 
                                        dim.height/2-frame.getSize().height/2);

screenshot

GridPane儿童中心

您需要添加

GridPane.setHalignment(child, HPos.CENTER);

到您的代码中,删除其余不必要的代码

我编辑了你的代码:

{
    Label statusLabel = new Label("Checking for Updates...");
    //statusLabel.setAlignment(Pos.CENTER);
    //statusLabel.setTextAlignment(TextAlignment.CENTER);
    rootGrid.add(statusLabel, 0, 0);
    GridPane.setHalignment(statusLabel, HPos.CENTER);
}
{
    ProgressBar progressBar = new ProgressBar();
    progressBar.setProgress(-1);
    progressBar.setPrefWidth(400); // 1/5 the width of the screen
    rootGrid.add(progressBar, 0, 1);
}
{
    Button downloadButton = new Button("Get it!");
    //downloadButton.setAlignment(Pos.CENTER);
    rootGrid.add(downloadButton, 0, 2);
    GridPane.setHalignment(downloadButton, HPos.CENTER);
}

结果是

enter image description here


推荐