拥有最小化按钮效果

时间:2018-06-13 12:12:05

标签: java javafx icons minimize

axon.amqp.exchange=Exchange

我有一个图标,通过鼠标点击最小化我的程序。例如,当我为程序最小化Windows时,您可以看到程序如何使用效果。程序慢慢移回任务栏。我也希望有这样的效果。如果我使用顶部的代码执行此操作,程序就在系统托盘中。我如何获得这样的效果?

1 个答案:

答案 0 :(得分:1)

在想要图标化应用程序时动画窗口大小,并在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();
            }
        }
    }

}