我想创建一个自定义Dialog
,它只显示选项(参见图 1)。如果用户选择这些选项之一,对话框应关闭并立即返回相应的结果。
到目前为止,我只能通过向 Dialog
添加任意 ButtonType
来实现此目的,并使用 setVisible(false)
隐藏它,在单击选项的 EventHandler
中应用 fire()
。
这个奇怪的解决方法实际上工作得很好,但在我看来非常不专业......
那么,在不使用 ButtonType 技巧的情况下,如何以更专业或更正确的方式做到这一点?
我的解决方法代码如下所示(对话框类):
public class CustomDialog extends Dialog<String> {
private static final String[] OPTIONS
= new String[]{"Option1", "Option2", "Option3", "Option4"};
private String selectedOption = null;
Button applyButton;
public CustomDialog() {
super();
initStyle(StageStyle.DECORATED);
VBox vBox = new VBox();
for (String option : OPTIONS) {
Button optionButton = new Button(option);
optionButton.setOnAction((event) -> {
selectedOption = option;
applyButton.fire();
});
vBox.getChildren().add(optionButton);
}
getDialogPane().setContent(vBox);
getDialogPane().getButtonTypes().add(ButtonType.APPLY);
applyButton = (Button) getDialogPane().lookupButton(ButtonType.APPLY);
applyButton.setVisible(false);
setResultConverter((dialogButton) -> {
return selectedOption;
});
}
}
使用对话框类:
CustomDialog dialog = new CustomDialog();
Optional<String> result = dialog.showAndWait();
String selected = null;
if (result.isPresent()) {
selected = result.get();
} else if (selected == null) {
System.exit(0);
}
最佳答案
Dialog
只是一个显示 DialogPane
的窗口,并且引用 Javadocs for DialogPane
:
DialogPane
operates on the concept ofButtonType
. AButtonType
is a descriptor of a single button that should be represented visually in theDialogPane
. Developers who create aDialogPane
therefore must specify the button types that they want to display
(我的重点)。因此,虽然您已经展示了一种可能的解决方法,并且在另一个答案 Slaw 中展示了另一种解决方法,但如果您尝试使用 Dialog
而不使用 ButtonType
及其关联结果转换器,您实际上是在将 Dialog
类用于其不适合的用途。
您所描述的功能可以通过常规模态Stage
完美实现。例如,以下给出了您所描述的相同基本行为,并且不涉及 ButtonType
:
package org.jamesd.examples.dialog;
import java.util.Optional;
import java.util.stream.Stream;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.layout.VBox;
import javafx.stage.Modality;
import javafx.stage.Stage;
import javafx.stage.Window;
public class CustomDialog {
private static final String[] OPTIONS
= {"Option 1", "Option 2", "Option 3", "Option 4"};
private final Stage stage ;
private String selectedOption = null ;
public CustomDialog() {
this(null);
}
public CustomDialog(Window parent) {
var vbox = new VBox();
// Real app should use an external style sheet:
vbox.setStyle("-fx-padding: 12px; -fx-spacing: 5px;");
Stream.of(OPTIONS)
.map(this::createButton)
.forEach(vbox.getChildren()::add);
var scene = new Scene(vbox);
stage = new Stage();
stage.initOwner(parent);
stage.initModality(Modality.WINDOW_MODAL);
stage.setScene(scene);
}
private Button createButton(String text) {
var button = new Button(text);
button.setOnAction(e -> {
selectedOption = text ;
stage.close();
});
return button ;
}
public Optional<String> showDialog() {
selectedOption = null ;
stage.showAndWait();
return Optional.ofNullable(selectedOption);
}
}
这是一个使用此自定义对话框的简单应用程序类:
package org.jamesd.examples.dialog;
import javafx.application.Application;
import javafx.application.Platform;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.Label;
import javafx.scene.layout.VBox;
import javafx.stage.Stage;
public class App extends Application {
@Override
public void start(Stage stage) throws Exception {
var root = new VBox();
// Real app should use an external style sheet:
root.setStyle("-fx-padding: 12px; -fx-spacing: 5px;");
var showDialog = new Button("Show dialog");
var label = new Label("No option chosen");
showDialog.setOnAction(e ->
new CustomDialog(stage)
.showDialog()
.ifPresentOrElse(label::setText, Platform::exit));
root.getChildren().addAll(showDialog, label);
stage.setScene(new Scene(root));
stage.show();
}
}
关于java - 如何在不使用任何 "ButtonType"控件的情况下在 JavaFx 中创建自定义对话框?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/60102226/