JavaFX - 为什么更改对话框的 header 文本会使按钮栏不可见?
JavaFX - Why does changing the header text of a dialog make the button bar invisible?
这是我的自定义对话框中的一个小示例,用于显示 运行 javafx.concurrent.Task
.
的进度
DialogPane pane = this.getDialogPane()
pane.getButtonTypes().addAll(ButtonType.CANCEL);
pane.headerTextProperty().bind(task.titleProperty());
pane.contentTextProperty().bind(task.messageProperty());
由于某种原因,按钮栏中的按钮消失了,但只是在更新了一些文本之后。进一步调查,我发现绑定一个对话框的header文本似乎把按钮栏中的所有按钮都去掉了。为什么会发生这种情况,我该怎么做才能阻止按钮被隐藏?
编辑:这是一个演示问题的 MCVE。
import javafx.application.Application;
import javafx.beans.property.ObjectProperty;
import javafx.beans.property.SimpleObjectProperty;
import javafx.concurrent.Task;
import javafx.scene.Scene;
import javafx.scene.control.*;
import javafx.scene.layout.StackPane;
import javafx.stage.Modality;
import javafx.stage.Stage;
public class MCVE extends Application {
public static class CustomDialog extends Dialog<ButtonType> {
public CustomDialog(Task<?> task) {
this.initModality(Modality.APPLICATION_MODAL);
DialogPane pane = this.getDialogPane();
{
pane.getButtonTypes().addAll(ButtonType.CANCEL);
pane.headerTextProperty().bind(task.titleProperty());
}
setOnCloseRequest(event -> {
if (task.isRunning()) event.consume();
});
}
}
public static void main(String[] args) {
launch(args);
}
@Override
public void start(Stage stage) {
StackPane root = new StackPane();
Button starter = new Button("Showcase");
starter.setMaxSize(Double.MAX_VALUE, Double.MAX_VALUE);
root.getChildren().add(starter);
Scene scene = new Scene(root, 500, 500);
stage.setScene(scene);
stage.show();
starter.setOnAction(event -> {
Task<Void> task = new Task<>() {
@Override
protected Void call() throws Exception {
updateTitle("Before loop");
try {
Thread.sleep(1000);
} catch (InterruptedException ignored) {
if (isCancelled()) return null;
}
for (int i = 1; i <= 20; i++) {
updateTitle("loop " + i);
try {
Thread.sleep(1000);
} catch (InterruptedException ignored) {
if (isCancelled()) return null;
}
}
return null;
}
};
Thread worker = new Thread(task);
worker.start();
new CustomDialog(task).showAndWait();
});
}
}
看来问题需要在 JavaFX 端解决。事实上,按钮栏只是被推到了视线之外。虽然有一个相对不错的解决方法。 Dialog
内部使用样式化的 GridPane
来显示 header 文本和图形,因此我只是使用外部 GridPane
复制了它,而不是绑定到 textProperty()
Label
.
public static class CustomDialog extends Dialog<ButtonType> {
public CustomDialog(Task<?> task) {
DialogPane pane = this.getDialogPane(); {
pane.getButtonTypes().addAll(ButtonType.CANCEL);
//construct custom header
GridPane headerRoot = new GridPane(); {
Label headerText = new Label();
//headerText is the label containing the header text
headerText.textProperty().bind(task.titleProperty());
headerRoot.add(headerText, 0, 0);
}
headerRoot.getStyleClass().addAll("header-panel");
pane.setHeader(headerRoot);
pane.setContentText("Placeholder content");
pane.getScene().getWindow().setOnCloseRequest(event -> {
if (!task.isDone()) {
event.consume();
}
});
}
}
看起来和默认对话框一模一样,没有上面问题提到的问题。
这是我的自定义对话框中的一个小示例,用于显示 运行 javafx.concurrent.Task
.
DialogPane pane = this.getDialogPane()
pane.getButtonTypes().addAll(ButtonType.CANCEL);
pane.headerTextProperty().bind(task.titleProperty());
pane.contentTextProperty().bind(task.messageProperty());
由于某种原因,按钮栏中的按钮消失了,但只是在更新了一些文本之后。进一步调查,我发现绑定一个对话框的header文本似乎把按钮栏中的所有按钮都去掉了。为什么会发生这种情况,我该怎么做才能阻止按钮被隐藏?
编辑:这是一个演示问题的 MCVE。
import javafx.application.Application;
import javafx.beans.property.ObjectProperty;
import javafx.beans.property.SimpleObjectProperty;
import javafx.concurrent.Task;
import javafx.scene.Scene;
import javafx.scene.control.*;
import javafx.scene.layout.StackPane;
import javafx.stage.Modality;
import javafx.stage.Stage;
public class MCVE extends Application {
public static class CustomDialog extends Dialog<ButtonType> {
public CustomDialog(Task<?> task) {
this.initModality(Modality.APPLICATION_MODAL);
DialogPane pane = this.getDialogPane();
{
pane.getButtonTypes().addAll(ButtonType.CANCEL);
pane.headerTextProperty().bind(task.titleProperty());
}
setOnCloseRequest(event -> {
if (task.isRunning()) event.consume();
});
}
}
public static void main(String[] args) {
launch(args);
}
@Override
public void start(Stage stage) {
StackPane root = new StackPane();
Button starter = new Button("Showcase");
starter.setMaxSize(Double.MAX_VALUE, Double.MAX_VALUE);
root.getChildren().add(starter);
Scene scene = new Scene(root, 500, 500);
stage.setScene(scene);
stage.show();
starter.setOnAction(event -> {
Task<Void> task = new Task<>() {
@Override
protected Void call() throws Exception {
updateTitle("Before loop");
try {
Thread.sleep(1000);
} catch (InterruptedException ignored) {
if (isCancelled()) return null;
}
for (int i = 1; i <= 20; i++) {
updateTitle("loop " + i);
try {
Thread.sleep(1000);
} catch (InterruptedException ignored) {
if (isCancelled()) return null;
}
}
return null;
}
};
Thread worker = new Thread(task);
worker.start();
new CustomDialog(task).showAndWait();
});
}
}
看来问题需要在 JavaFX 端解决。事实上,按钮栏只是被推到了视线之外。虽然有一个相对不错的解决方法。 Dialog
内部使用样式化的 GridPane
来显示 header 文本和图形,因此我只是使用外部 GridPane
复制了它,而不是绑定到 textProperty()
Label
.
public static class CustomDialog extends Dialog<ButtonType> {
public CustomDialog(Task<?> task) {
DialogPane pane = this.getDialogPane(); {
pane.getButtonTypes().addAll(ButtonType.CANCEL);
//construct custom header
GridPane headerRoot = new GridPane(); {
Label headerText = new Label();
//headerText is the label containing the header text
headerText.textProperty().bind(task.titleProperty());
headerRoot.add(headerText, 0, 0);
}
headerRoot.getStyleClass().addAll("header-panel");
pane.setHeader(headerRoot);
pane.setContentText("Placeholder content");
pane.getScene().getWindow().setOnCloseRequest(event -> {
if (!task.isDone()) {
event.consume();
}
});
}
}
看起来和默认对话框一模一样,没有上面问题提到的问题。