java - 自带最小化按钮效果

标签 java javafx icons minimize

@FXML
void minimize(MouseEvent event) {
    Stage stage=(Stage) iconMinimize.getScene().getWindow();
    stage.setIconified(true);
}

我有一个图标,可以通过单击鼠标来最小化我的程序。例如,当我最小化某个程序的Windows时,您可以看到该程序的工作效果和效果。程序慢慢移回到任务栏。我也想有这样的效果。如果我使用顶部的代码执行此操作,则该程序就位于系统托盘中。怎样才能达到这样的效果呢?

最佳答案

当您想要图标化应用程序时,对窗口大小进行动画处理,并在 Stage 恢复时监听 iconified 属性来执行反向动画:

@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();
            }
        }
    }

}

关于java - 自带最小化按钮效果,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50836980/

相关文章:

maven - mvnrepository.com 上的图标和标签

java - Android SQLite 游标错误

graph - 在 javafx 2.2 散点图中隐藏轴

grails - Grails-将提交按钮更改为fa icom

jakarta-ee - JFXtras 和 FXML 互操作性

javafx Glow 粉碎动画

Delphi 的功能区图像出现故障

java - Android中的Sqlite更新查询

java - 将 JComponent 添加到小程序的 Pane 中

java - SpringFox Swagger - 模型中的可选和必填字段