Там есть способ, который можно переместить диалоговое окно предупреждения, с помощью его yProperty()
. Вместо перехода по маршруту мы будем использовать временную шкалу для установки этого свойства. Но так как это свойство только для чтения, нам нужно использовать DoubleProperty
в рамках перехода и использовать Alert.setY()
.
Первая часть вашего вопроса, скользящая в диалоговом окне, проста. Второй, сползающий, более сложный, так как диалог закрывается сразу после нажатия кнопки.
Решение 1. Просто сдвинув в
Нам нужны диалоговые размеры и положение, и для этого нам нужно, чтобы показать его. Это означает, что он будет показан и сразу перемещен в верхнюю часть экрана.
Поэтому я изменю alert.showAndWait()
на alert.show()
.
@Override
public void start(Stage primaryStage) {
Button btn = new Button();
btn.setText("Show Sliding In Alert Dialog");
btn.setOnAction(event -> {
Alert alert = new Alert(AlertType.CONFIRMATION);
alert.setTitle("Confirmation Dialog");
alert.setHeaderText("Look, a Confirmation Dialog");
alert.setContentText("Are you ok with this?");
ButtonBar buttonBar=(ButtonBar)alert.getDialogPane().lookup(".button-bar");
buttonBar.setDisable(true);
alert.initModality(Modality.APPLICATION_MODAL);
alert.show();
// now we can retrive alert bounds:
double yIni=-alert.getHeight();
double yEnd=alert.getY();
// and move alert to the top of the screen
alert.setY(yIni);
final DoubleProperty yProperty = new SimpleDoubleProperty();
yProperty.addListener((ob,n,n1)->alert.setY(n1.doubleValue()));
Timeline timeIn = new Timeline();
timeIn.getKeyFrames().add(
new KeyFrame(Duration.seconds(1.5),
e->buttonBar.setDisable(false),
new KeyValue(yProperty, yEnd,Interpolator.EASE_BOTH)));
timeIn.play();
alert.resultProperty().addListener((ob,r,r1)->{
if (r1 == ButtonType.OK){
// alert is closed and hidden in its final position
}
else{
primaryStage.close();
}
});
});
StackPane root = new StackPane();
root.getChildren().add(btn);
Scene scene = new Scene(root, 300, 250);
primaryStage.setTitle("Hello World!");
primaryStage.setScene(scene);
primaryStage.show();
}
Слушатель в yProperty()
позволяют установить позицию в диалоге во всех различных положениях интерполированное во время перехода.
Решение 2. сползет в и из
Это немного грязного раствора, так как предполагает использование второго диалога Alert
, учитывая оригинал один закрыт кнопки один раз щелкнуть мышью. Мы добавим это второе диалоговое окно позади первого и используем его для создания эффекта выталкивания после первого закрытия.
Единственный побочный эффект, который вы заметите, - это быстрое мигание в фазе показа второго и установка первого над ним.
@Override
public void start(Stage primaryStage) {
Button btn = new Button();
btn.setText("Show Sliding In Alert Dialog");
btn.setOnAction(event -> {
Alert alert = new Alert(AlertType.CONFIRMATION);
alert.setTitle("Confirmation Dialog");
alert.setHeaderText("Look, a Confirmation Dialog");
alert.setContentText("Are you ok with this?");
Alert alertOut = new Alert(AlertType.CONFIRMATION);
alertOut.setTitle("Confirmation Dialog");
alertOut.setHeaderText("Look, a Confirmation Dialog");
alertOut.setContentText("Are you ok with this?");
alertOut.initModality(Modality.NONE);
((Stage)alertOut.getDialogPane().getScene().getWindow()).setOpacity(0);
ButtonBar buttonBar=(ButtonBar)alert.getDialogPane().lookup(".button-bar");
buttonBar.setDisable(true);
alert.initModality(Modality.APPLICATION_MODAL);
alert.show();
// now we can retrive alert bounds:
double yIni=-alert.getHeight();
double yEnd=alert.getY();
// and move alert to the top of the screen
alert.setY(yIni);
final DoubleProperty yProperty = new SimpleDoubleProperty();
yProperty.addListener((ob,n,n1)->alert.setY(n1.doubleValue()));
Timeline timeIn = new Timeline();
timeIn.getKeyFrames().add(
new KeyFrame(Duration.seconds(1.5),
e->{
buttonBar.setDisable(false);
// show second dialog
alertOut.show();
// move to front the first one
((Stage)alert.getDialogPane().getScene().
getWindow()).toFront();
}, new KeyValue(yProperty, yEnd,Interpolator.EASE_BOTH)));
timeIn.play();
alert.resultProperty().addListener((ob,r,r1)->{
if (r1 == ButtonType.OK){
// show second dialog
((Stage)alertOut.getDialogPane().getScene().getWindow()).setOpacity(1);
ButtonBar buttonBarOut=(ButtonBar)alertOut.getDialogPane().lookup(".button-bar");
buttonBarOut.setDisable(true);
final DoubleProperty yPropertyOut = new SimpleDoubleProperty(yEnd);
yPropertyOut.addListener((ov,n,n1)->alertOut.setY(n1.doubleValue()));
// Create slide out transition
Timeline timeOut = new Timeline();
timeOut.getKeyFrames().add(
new KeyFrame(Duration.seconds(1.5),
e->alertOut.close(),
new KeyValue(yPropertyOut, yIni,Interpolator.EASE_BOTH)));
timeOut.play();
}
else{
alertOut.close();
primaryStage.close();
}
});
});
StackPane root = new StackPane();
root.getChildren().add(btn);
Scene scene = new Scene(root, 300, 250);
primaryStage.setTitle("Hello World!");
primaryStage.setScene(scene);
primaryStage.show();
}
EDIT
Решение 2. Улучшение слайдов и аудиовыход
Я нашел способ использовать один диалог, и обеспечить слайд из эффекта тоже.
Все, что требуется, - это захватить действие щелчка на выбранной кнопке, уничтожить событие, добавить туда переход на слайд и скрыть диалоговое окно.
@Override
public void start(Stage primaryStage) {
Button btn = new Button();
btn.setText("Show Sliding In Alert Dialog");
btn.setOnAction(event -> {
Alert alert = new Alert(AlertType.CONFIRMATION);
alert.setTitle("Confirmation Dialog");
alert.setHeaderText("Look, a Confirmation Dialog");
alert.setContentText("Are you ok with this?");
ButtonBar buttonBar=(ButtonBar)alert.getDialogPane().lookup(".button-bar");
buttonBar.setDisable(true);
alert.initModality(Modality.APPLICATION_MODAL);
alert.show();
// now we can retrive alert bounds:
double yIni=-alert.getHeight();
double yEnd=alert.getY();
// and move alert to the top of the screen
alert.setY(yIni);
buttonBar.getButtons().stream().filter(b->((Button)b).isDefaultButton()).findFirst()
.ifPresent(b->((Button)b).addEventFilter(EventType.ROOT,
e->{
if(e.getEventType().equals(ActionEvent.ACTION)){
e.consume();
final DoubleProperty yPropertyOut = new SimpleDoubleProperty(yEnd);
yPropertyOut.addListener((ov,n,n1)->alert.setY(n1.doubleValue()));
Timeline timeOut = new Timeline();
timeOut.getKeyFrames().add(new KeyFrame(Duration.seconds(1.5), t->alert.close(),
new KeyValue(yPropertyOut, yIni,Interpolator.EASE_BOTH)));
timeOut.play();
}
}));
final DoubleProperty yProperty = new SimpleDoubleProperty();
yProperty.addListener((ob,n,n1)->alert.setY(n1.doubleValue()));
Timeline timeIn = new Timeline();
timeIn.getKeyFrames().add(new KeyFrame(Duration.seconds(1.5), e->{
buttonBar.setDisable(false);
},new KeyValue(yProperty, yEnd,Interpolator.EASE_BOTH)));
timeIn.play();
});
StackPane root = new StackPane();
root.getChildren().add(btn);
Scene scene = new Scene(root, 300, 250);
primaryStage.setTitle("Hello World!");
primaryStage.setScene(scene);
primaryStage.show();
}
Прохладный, я, вероятно, воспользуюсь первым решением и попытаюсь настроить его так, чтобы кнопка просто пришла и выходила автоматически. –
Спасибо, я также выберу первый ... –
Можете ли вы вкратце объяснить, что делает Interpolator.EASE_BOTH? –