#javafx
#javafx
Вопрос:
Здесь я хочу создать пользовательский диалог, который работает как Alert
, с красивым пользовательским интерфейсом; «ShowDialog.fxml» — это DialogPane
.
Я пытался JFXDialog
, но он не ждет и не дает мне выбора пользователей. Есть ли какой-нибудь способ получить хороший result
? Заранее спасибо.
Это моя Alert
реализация:
primaryStage.setOnCloseRequest(event -> {
Alert alert = new Alert(Alert.AlertType.CONFIRMATION);
alert.setTitle("Выход");
alert.setHeaderText("Are you really want to exit ?");
ButtonType yes = new ButtonType("Yes");
ButtonType no = new ButtonType("No");
alert.getButtonTypes().clear();
alert.getButtonTypes().addAll(yes, no);
Optional<ButtonType> option = alert.showAndWait();
if (option.get() == yes) {
System.exit(0);
} else {
alert.close();
event.consume();
}
}
Это что-то новенькое.
primaryStage.setOnCloseRequest(event -> {
FXMLLoader loader = new FXMLLoader(getClass().getResource("/views/common/showDialog.fxml"));
ShowDialogController controller = loader.getController();
Dialog<JFXButton> dialog = new Dialog<>();
DialogPane confirmationDialogView = null;
try {
dialog.setDialogPane(loader.load());
} catch (IOException e) {
e.printStackTrace();
}
dialog.showAndWait();
}
И это файл FXML:
<?xml version="1.0" encoding="UTF-8"?>
<?import com.jfoenix.controls.JFXButton?>
<?import de.jensd.fx.glyphs.octicons.OctIconView?>
<?import javafx.geometry.Insets?>
<?import javafx.scene.control.DialogPane?>
<?import javafx.scene.control.Label?>
<?import javafx.scene.layout.AnchorPane?>
<?import javafx.scene.layout.ColumnConstraints?>
<?import javafx.scene.layout.GridPane?>
<?import javafx.scene.layout.RowConstraints?>
<?import javafx.scene.text.Font?>
<DialogPane prefHeight="400.0" prefWidth="900.0" styleClass="main_color_green" stylesheets="@../../css/style.css" xmlns="http://javafx.com/javafx/8.0.171" xmlns:fx="http://javafx.com/fxml/1">
<graphic>
<AnchorPane prefHeight="400.0" prefWidth="900.0" styleClass="main_color_green" stylesheets="@../../css/style.css">
<GridPane layoutX="161.0" layoutY="84.0" AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="0.0">
<columnConstraints>
<ColumnConstraints hgrow="SOMETIMES" minWidth="10.0" percentWidth="30.0" prefWidth="100.0" />
<ColumnConstraints hgrow="SOMETIMES" minWidth="10.0" prefWidth="100.0" />
</columnConstraints>
<rowConstraints>
<RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="SOMETIMES" />
</rowConstraints>
<GridPane>
<columnConstraints>
<ColumnConstraints hgrow="SOMETIMES" minWidth="10.0" prefWidth="100.0" />
</columnConstraints>
<rowConstraints>
<RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="SOMETIMES" />
</rowConstraints>
<OctIconView fx:id="octionIconView" fill="WHITE" glyphName="ALERT" size="200" wrappingWidth="198.0" GridPane.halignment="CENTER" GridPane.valignment="CENTER" />
</GridPane>
<GridPane GridPane.columnIndex="1">
<columnConstraints>
<ColumnConstraints hgrow="SOMETIMES" minWidth="10.0" prefWidth="100.0" />
</columnConstraints>
<rowConstraints>
<RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="SOMETIMES" />
<RowConstraints minHeight="10.0" percentHeight="30.0" prefHeight="30.0" vgrow="SOMETIMES" />
</rowConstraints>
<JFXButton fx:id="btnNo" prefHeight="94.0" prefWidth="295.0" styleClass="dialogBtn" stylesheets="@../../css/btn.css" text="НЕТ" GridPane.halignment="LEFT" GridPane.rowIndex="1" GridPane.valignment="CENTER">
<GridPane.margin>
<Insets left="50.0" />
</GridPane.margin>
</JFXButton>
<JFXButton fx:id="btnYes" prefHeight="94.0" prefWidth="337.0" styleClass="dialogBtn" stylesheets="@../../css/btn.css" text="ДА" GridPane.halignment="RIGHT" GridPane.rowIndex="1" GridPane.valignment="CENTER">
<GridPane.margin>
<Insets right="50.0" />
</GridPane.margin>
</JFXButton>
<Label fx:id="labelInformation" alignment="CENTER" text="Label" textFill="WHITE" GridPane.halignment="CENTER" GridPane.valignment="CENTER">
<font>
<Font size="24.0" />
</font>
</Label>
</GridPane>
</GridPane>
</AnchorPane>
</graphic>
</DialogPane>
Ответ №1:
Диалоги в JavaFX являются экземпляром диалогового окна класса ШАБЛОНА<R>. Где R — возвращаемый тип (если отсутствует, по умолчанию используется buttonType).
Для вашей собственной реализации диалога вы должны развернуть Dialog и e если вы хотите получить из него данные другого типа, отправьте ResultConverter (экземпляр обратного вызова<buttonType, R> ). Другой вариант получения результата диалога — вручную вызвать SetResult и затем закрыть диалоговое окно.
Когда вы хотите использовать FXML, вы обычно используете структуру своего диалогового окна для загрузки нужной диалоговой панели из соответствующего файла fxml.
Вот пример:
<DialogPane xmlns="http://javafx.com/javafx" xmlns:fx="http://javafx.com/fxml" prefWidth="500">
<content>
<GridPane hgap="5" vgap="5">
<Label text="Адрес на хост:" GridPane.columnIndex="0" GridPane.rowIndex="0"/>
<TextField fx:id="hostnameTextField" GridPane.columnIndex="1" GridPane.rowIndex="0"/>
<Label text="База данни:" GridPane.columnIndex="0" GridPane.rowIndex="1"/>
<TextField fx:id="databaseTextField" GridPane.columnIndex="1" GridPane.rowIndex="1"/>
<Label text="Потребителско име:" GridPane.columnIndex="0" GridPane.rowIndex="2"/>
<TextField fx:id="usernameTextField" prefWidth="200" GridPane.columnIndex="1" GridPane.rowIndex="2" GridPane.fillWidth="false"/>
<Label text="Парола:" GridPane.columnIndex="0" GridPane.rowIndex="3"/>
<PasswordField fx:id="passwordField" prefWidth="200" GridPane.columnIndex="1" GridPane.rowIndex="3" GridPane.fillWidth="false"/>
<columnConstraints>
<ColumnConstraints/>
<ColumnConstraints hgrow="ALWAYS"/>
</columnConstraints>
</GridPane>
</content>
<buttonTypes>
<ButtonType fx:id="connectButtonType" text="Свързване" buttonData="OK_DONE"/>
<ButtonType text="Затвори" buttonData="CANCEL_CLOSE"/>
</buttonTypes>
</DialogPane>
public class ConnectDialog extends Dialog<Connection> {
@FXML
private TextField hostnameTextField;
@FXML
private TextField databaseTextField;
@FXML
private TextField usernameTextField;
@FXML
private PasswordField passwordField;
@FXML
private ButtonType connectButtonType;
private ObjectProperty<Connection> connection = new SimpleObjectProperty<>(null);
public ConnectDialog(Window owner) {
try {
FXMLLoader loader = new FXMLLoader();
loader.setLocation(getClass().getResource("/com/xelapos/gui/client/dialog/dialog_pane_connect.fxml"));
loader.setController(this);
DialogPane dialogPane = loader.load();
dialogPane.lookupButton(connectButtonType).addEventFilter(ActionEvent.ANY, this::onConnect);
initOwner(owner);
initModality(Modality.APPLICATION_MODAL);
setResizable(true);
setTitle("Свързване с база данни");
setDialogPane(dialogPane);
setResultConverter(buttonType -> {
if(!Objects.equals(ButtonBar.ButtonData.OK_DONE, buttonType.getButtonData())) {
return null;
}
return connection.getValue();
});
setOnShowing(dialogEvent -> Platform.runLater(() -> hostnameTextField.requestFocus()));
}
catch (IOException e) {
throw new RuntimeException(e);
}
}
@FXML
private void initialize() {
}
@FXML
private void onConnect(ActionEvent event) {
String jdbcUrl = String.format(
"jdbc:postgresql://%s/%s",
hostnameTextField.textProperty().getValueSafe(),
databaseTextField.textProperty().getValueSafe()
);
try {
Connection conn = DriverManager.getConnection(jdbcUrl, usernameTextField.textProperty().getValueSafe(), passwordField.textProperty().getValueSafe());
connection.setValue(conn);
return;
}
catch (SQLException e) {
Alert alert = new Alert(Alert.AlertType.ERROR);
alert.initOwner(getDialogPane().getScene().getWindow());
alert.initModality(Modality.APPLICATION_MODAL);
alert.setResizable(true);
alert.setTitle(getTitle());
alert.setHeaderText(null);
alert.setContentText(e.getLocalizedMessage());
alert.show();
}
event.consume();
}
}
И, конечно же, использование:
ConnectDialog dialog = new ConnectDialog(stage);
dialog.showAndWait().ifPresent(conn -> {
System.out.println("Open connection!");
connection.setValue(conn);
});
Комментарии:
1. Я не знал, что есть конвертер результатов для диалогов, спасибо за это 🙂
Ответ №2:
Вот реализация MessageBox, которая расширяет Alert
класс. Если вы хотите добавить стиль CSS для украшения вашего окна, вы должны определить MessageBox.setStyleSheet
при загрузке вашего приложения (только один раз, нет необходимости вызывать его каждый раз, когда вы хотите отобразить MessageBox
):
public class Main extends Application {
@Override
public void start(Stage primaryStage) throws Exception {
MessageBox.setStyleSheet("/your/path/.../message-box.css");
...
primaryStage.setOnCloseRequest(event -> {
try {
MessageBox dialog = new MessageBox(AlertType.CONFIRMATION, primaryStage, "Do you really want to exit?", ButtonType.YES, ButtonType.NO);
dialog.setTitle("Выход");
Optional<ButtonType> option = dialog.showAndWait();
if (option != null amp;amp; option.get() == ButtonType.YES)
System.exit(0);
else {
dialog.close();
event.consume();
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
Вы можете проверить message-box.css, хотите ли вы настроить стиль компонента.