Собственная кнопка свертывания с эффектом - PullRequest
0 голосов
/ 13 июня 2018
@FXML
void minimize(MouseEvent event) {
    Stage stage=(Stage) iconMinimize.getScene().getWindow();
    stage.setIconified(true);
}

У меня есть значок, который минимизирует мою программу по щелчку мыши.Например, когда я сворачиваю Windows для программы, вы можете увидеть, как программа работает с эффектом.Программа медленно возвращается на панель задач.Я бы тоже хотел иметь такой эффект.Если я сделаю это с кодом сверху, программа находится прямо в системном трее.Как мне получить такой эффект?

1 Ответ

0 голосов
/ 13 июня 2018

Анимируйте размер окна, когда вы хотите создать иконку приложения, и прослушайте свойство iconified, чтобы выполнить обратную анимацию при восстановлении Stage:

@Override
public void start(Stage primaryStage) {
    StageHideAnimator.create(primaryStage);

    Button minimize = new Button("minimize");
    minimize.setOnAction(evt -> {
        StageHideAnimator animator = StageHideAnimator.getStageHideAnimator((Node) evt.getSource());
        animator.iconify();
    });

    Button close = new Button("close");
    close.setOnAction(evt -> primaryStage.close());

    VBox content = new VBox(minimize, close, new Rectangle(200, 200, Color.BLUE));
    content.setPadding(new Insets(10));
    content.setStyle("-fx-background-color: green;");

    primaryStage.initStyle(StageStyle.TRANSPARENT);

    Scene scene = new Scene(content);

    primaryStage.setScene(scene);
    primaryStage.setOnShown(evt -> {
        WindowUtils.placeAtPrimaryScreenBottom(primaryStage);
    });
    primaryStage.show();
}
public final class WindowUtils {

    private WindowUtils() { }

    public static void placeAtPrimaryScreenBottom(Stage stage) {
        stage.setY(Screen.getPrimary().getVisualBounds().getMaxY() - stage.getHeight());
    }

}
public class StageHideAnimator {

    // key used for storing animators in the properties map of a Stage
    private static final Object PROPERTY_KEY = new Object();

    private double sceneHeight;
    private double decorationHeight;
    private final Stage stage;
    private Timeline animation;

    // fraction of height relative to full height
    private final DoubleProperty height = new SimpleDoubleProperty();

    // getter for the animator
    public static StageHideAnimator getStageHideAnimator(Stage stage) {
        return (StageHideAnimator) stage.getProperties().get(PROPERTY_KEY);
    }

    // get animator of window containing the node
    public static StageHideAnimator getStageHideAnimator(Node node) {
        return getStageHideAnimator((Stage) node.getScene().getWindow());
    }

    private StageHideAnimator(Stage stage) {
        this.stage = stage;
        stage.iconifiedProperty().addListener((o, oldValue, newValue) -> {
            // do reverse hide animation when stage is shown
            if (!newValue) {
                animation.setRate(-1);

                if (animation.getStatus() == Animation.Status.STOPPED) {
                    animation.playFrom("end");
                } else {
                    animation.play();
                }
            }
        });
        height.addListener((o, oldValue, newValue) -> {
            // resize stage and put it at the bottom of the primary screen
            stage.setHeight(sceneHeight * newValue.doubleValue() + decorationHeight);
            WindowUtils.placeAtPrimaryScreenBottom(stage);
        });
    }

    public static StageHideAnimator create(Stage stage) {
        if (stage.getProperties().containsKey(PROPERTY_KEY)) {
            // don't allow 2 animators
            throw new IllegalArgumentException("animator already exists");
        }

        StageHideAnimator animator = new StageHideAnimator(stage);
        stage.getProperties().put(PROPERTY_KEY, animator);
        return animator;
    }

    private void initHeight() {
        sceneHeight = stage.getScene().getHeight();
        decorationHeight = stage.getHeight() - sceneHeight;
    }

    public void iconify() {
        if (stage.isIconified()) {
            return;
        }

        if (animation == null) {
            initHeight(); // save initial height of stage

            animation = new Timeline(
                    new KeyFrame(Duration.ZERO, new KeyValue(height, 1d, Interpolator.EASE_BOTH)),
                    new KeyFrame(Duration.seconds(1), new KeyValue(height, 0d, Interpolator.EASE_BOTH)));

            animation.setOnFinished(evt -> {
                if (animation.getRate() == 1) {
                    // iconify at end of hiding animation
                    animation.setRate(-1);
                    stage.setIconified(true);
                }
            });

            animation.play();
        } else {
            animation.setRate(1);
            if (animation.getStatus() == Animation.Status.STOPPED) {
                initHeight(); // save initial height of stage
                animation.playFromStart();
            } else {
                animation.play();
            }
        }
    }

}
...