javafx - 如何垂直居中Alert/DialogPane的内容?

标签 javafx

我创建了一个未修饰Alert,并且我希望内容在Alert中居中。但是,底部似乎有一些填充,我无法摆脱。

这是一个 MCVE:

import javafx.application.Application;
import javafx.geometry.Insets;
import javafx.geometry.Pos;
import javafx.scene.control.Alert;
import javafx.scene.control.DialogPane;
import javafx.scene.control.Label;
import javafx.scene.control.ProgressIndicator;
import javafx.scene.layout.HBox;
import javafx.stage.Stage;
import javafx.stage.StageStyle;

public class Main extends Application {

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

    @Override
    public void start(Stage primaryStage) {

        Alert alert = new Alert(Alert.AlertType.NONE);

        DialogPane pane = new DialogPane();
        HBox contentPane = new HBox(10);
        contentPane.setPadding(new Insets(10));
        contentPane.setAlignment(Pos.CENTER);

        // Add progress indicator and label to contentPane
        contentPane.getChildren().addAll(
                new ProgressIndicator(ProgressIndicator.INDETERMINATE_PROGRESS) {{
                    setPrefSize(30, 30);
                }},
                new Label("Loading ...")
        );

        // Add border to demonstate the lower padding
        contentPane.setStyle("-fx-border-color: black");

        pane.setPadding(new Insets(10));
        pane.setStyle("-fx-border-color: black");
        pane.setContent(contentPane);
        alert.setDialogPane(pane);

        alert.initStyle(StageStyle.UNDECORATED);
        alert.showAndWait();

    }
}

结果是这个窗口:

Screenshot

如何创建底部没有间隙的 AlertDialogPane

最佳答案

使用:

import javafx.application.Application;
import javafx.geometry.Insets;
import javafx.geometry.Pos;
import javafx.scene.control.Alert;
import javafx.scene.control.Label;
import javafx.scene.control.ProgressIndicator;
import javafx.scene.layout.Border;
import javafx.scene.layout.BorderStroke;
import javafx.scene.layout.BorderStrokeStyle;
import javafx.scene.layout.BorderWidths;
import javafx.scene.layout.HBox;
import javafx.scene.paint.Color;
import javafx.scene.paint.Paint;
import javafx.stage.Stage;
import javafx.stage.StageStyle;

public class Main extends Application {

  private static Border createBorder(Paint stroke) {
    return new Border(new BorderStroke(stroke, BorderStrokeStyle.SOLID, 
                                       null, new BorderWidths(2)));
  }

  @Override
  public void start(Stage primaryStage) throws Exception {
    ProgressIndicator indicator = new ProgressIndicator();
    indicator.setPrefSize(30, 30);

    Label label = new Label("Loading...");
    label.setMinWidth(Label.USE_PREF_SIZE);

    HBox content = new HBox(10, indicator, label);
    content.setBorder(createBorder(Color.BLUE));
    content.setPadding(new Insets(10));
    content.setAlignment(Pos.CENTER);

    Alert alert = new Alert(Alert.AlertType.NONE);
    alert.initStyle(StageStyle.UNDECORATED);
    alert.getDialogPane().getStylesheets()
         .add(getClass().getResource("Main.css").toExternalForm());
    alert.getDialogPane().setPadding(new Insets(10));
    alert.getDialogPane().setContent(content);
    alert.getDialogPane().setBorder(createBorder(Color.RED));
    alert.show();
  }
}

这是Main.css:

.dialog-pane .button-bar .container {
  -fx-padding: 0px;
}

.dialog-pane:no-header .graphic-container {
  -fx-padding: 0px;
}

结果如下:

image of alert


我从 here (JavaFX CSS Reference) 获得的一些所需的样式类。然而,我主要是通过查看 modena.css (其中有 dialog-pane 的样式)来解决这个问题。


如果您不想使用外部 CSS,可以将 alert.getDialogPane().getStylesheets().add(...) 替换为:

alert.getDialogPane().applyCss(); // Seems to stop the lookup calls
                                  // from returning null
alert.getDialogPane()
     .lookup(".button-bar")
     .lookup(".container")
     .setStyle("-fx-padding: 0px;");
alert.getDialogPane().lookup(".graphic-container").setStyle("-fx-padding: 0px;");
alert.show();

根据您的评论进行更新。

我最初使用 Java 10.0.2 尝试过此操作,但我只是尝试使用 Java 8u181,它仍然对我有用。我注意到在您的 MCVE 中您使用的是 DialogPane,而我使用的是最初随 Alert 附带的 DialogPane >。请注意,仅当 NodeScene 的一部分时,applyCss() 方法才有效。显然,一旦 DialogPane 成为 Alert 的一部分,它就会成为 Scene 的一部分。因此,避免 NullPointerException 的一种方法是使用 Alert 附带的 DialogPane,就像我一样。

如果您仍想使用自己的 DialogPane,则只需在调用 applyCss() 之前调用 alert.setDialogPane 即可。但请注意,当我尝试此操作时,调用 lookup(".graphic-container") 仍然返回 null。我猜想 Node 只出现在原始 DialogPane 上。删除该 lookup 调用修复了该问题,而另一个 lookup 调用(对于 .button-bar > .container)仍然按预期工作。

所有这些看起来都是不应该依赖的实现行为,但它在 Java 8 和 Java 10 上都适用于我。不过,我会在更改 Java 版本时查看此代码,以防万一。

关于javafx - 如何垂直居中Alert/DialogPane的内容?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51883825/

相关文章:

Javafx和文件关联: opening the selected file

列中带有 ImageView 数组的 JavaFX TableView

JavaFX 未加载 GUI

javascript - 如何传递 webengine.executeScript() 使用的 javascript 对象

java - 为什么 JavaFX 包含重复的颜色常量?

multithreading - JavaFX 的 Swing 计时器替代方案和线程管理差异

java - 如何在 java 中使用 setText 更新 FXML 按钮 - 当它返回 java.lang.NullPointerException 错误时?

maven - 为什么 Bitbucket 无法构建我的 JFX 项目?

java - JavaFX 文本区域中的多种颜色

java - 如何在JavaFX中动态更新ListView单元格?