2015-04-25 2 views
1

Итак, я запускаю небольшое тестовое приложение, чтобы увидеть, возможно ли это, а затем переместить его в мой основной проект. Основная идея заключается в том, что диалоговое окно выходит из верхней части экрана в центр и ждет ответа от пользователя. Если они не нажали, программа завершится. Если они нажмут «да», диалоговое окно переместится от центра к верхнему экрану и исчезнет из поля зрения пользователя.Можно ли использовать переход пути в диалоговом окне в javafx?

package test; 

import java.util.Optional; 
import javafx.animation.PathTransition; 
import javafx.application.Application; 
import javafx.fxml.FXMLLoader; 
import javafx.scene.Scene; 
import javafx.scene.control.Alert; 
import javafx.scene.control.Alert.AlertType; 
import javafx.scene.control.ButtonType; 
import javafx.scene.layout.VBox; 
import javafx.scene.shape.MoveTo; 
import javafx.scene.shape.Path; 
import javafx.scene.shape.VLineTo; 
import javafx.stage.Stage; 
import javafx.util.Duration; 

public class Test extends Application 
{ 

    @Override 
    public void start(Stage stage) throws Exception 
    { 
     VBox root = FXMLLoader.load(getClass().getResource("FXMLDocument.fxml")); 

     Alert alert = new Alert(AlertType.CONFIRMATION); 
     alert.setTitle("Confirmation Dialog"); 
     alert.setHeaderText("Look, a Confirmation Dialog"); 
     alert.setContentText("Are you ok with this?"); 

     Path path = new Path(); 
     path.getElements().add(new MoveTo(300, -25)); 
     path.getElements().add(new VLineTo(200)); 
     PathTransition pathTransition = new PathTransition(); 
     pathTransition.setDuration(Duration.millis(1500)); 
     pathTransition.setPath(path); 
     pathTransition.setNode(alert); // This is where the problem lies. 
     pathTransition.setCycleCount(1); 
     pathTransition.play(); 

     Scene scene = new Scene(root, 640, 480); 

     stage.setScene(scene); 
     stage.show(); 

     Optional<ButtonType> result = alert.showAndWait(); 

     if (result.get() == ButtonType.OK) 
     { 
      Path path2 = new Path(); 
      path2.getElements().add(new MoveTo(300, 200)); 
      path2.getElements().add(new VLineTo(-25)); 
      PathTransition pathTransition2 = new PathTransition(); 
      pathTransition.setDuration(Duration.millis(1500)); 
      pathTransition.setPath(path); 
      pathTransition.setNode(alert); 
      pathTransition.setCycleCount(1); 
      pathTransition.play(); 
     } 
     else 
     { 
      stage.close(); 
     } 
    } 

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

} 

ответ

1

Там есть способ, который можно переместить диалоговое окно предупреждения, с помощью его 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(); 
} 
+0

Прохладный, я, вероятно, воспользуюсь первым решением и попытаюсь настроить его так, чтобы кнопка просто пришла и выходила автоматически. –

+0

Спасибо, я также выберу первый ... –

+0

Можете ли вы вкратце объяснить, что делает Interpolator.EASE_BOTH? –

Смежные вопросы