You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在JavaFX中实现Stage闪烁警示效果?

实现JavaFX模态Stage的点击警示闪烁效果

要实现类似Dialog的警示闪烁效果,核心是捕捉用户尝试点击其他窗口的动作,然后触发模态Stage的动画。具体实现如下:

1. 核心原理

当Stage设置为APPLICATION_MODAL时,用户点击其他窗口会触发系统向模态Stage发送WindowEvent.WINDOW_FOCUS_REQUESTED事件(系统试图让模态Stage重新获得焦点)。我们只需监听这个事件,在事件触发时播放闪烁动画即可。

2. 透明度闪烁实现

通过快速改变Stage的透明度实现闪烁效果,代码示例:

import javafx.animation.KeyFrame;
import javafx.animation.KeyValue;
import javafx.animation.Timeline;
import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.control.Label;
import javafx.stage.Modality;
import javafx.stage.Stage;
import javafx.stage.WindowEvent;
import javafx.util.Duration;

public class ModalFlashDemo extends Application {

    @Override
    public void start(Stage primaryStage) {
        // 初始化主窗口
        primaryStage.setTitle("主窗口");
        primaryStage.setScene(new Scene(new Label("点击我试试"), 300, 200));
        primaryStage.show();

        // 创建模态窗口
        Stage modalStage = new Stage();
        modalStage.initModality(Modality.APPLICATION_MODAL);
        modalStage.setTitle("模态窗口");
        modalStage.setScene(new Scene(new Label("我是模态窗口"), 200, 100));

        // 监听焦点请求事件,触发闪烁
        modalStage.addEventHandler(WindowEvent.WINDOW_FOCUS_REQUESTED, event -> flashByOpacity(modalStage));

        modalStage.show();
    }

    private void flashByOpacity(Stage stage) {
        // 构建透明度闪烁动画:1 -> 0.7 -> 1 -> 0.7 -> 1,持续400ms
        Timeline timeline = new Timeline(
                new KeyFrame(Duration.ZERO, new KeyValue(stage.opacityProperty(), 1.0)),
                new KeyFrame(Duration.millis(100), new KeyValue(stage.opacityProperty(), 0.7)),
                new KeyFrame(Duration.millis(200), new KeyValue(stage.opacityProperty(), 1.0)),
                new KeyFrame(Duration.millis(300), new KeyValue(stage.opacityProperty(), 0.7)),
                new KeyFrame(Duration.millis(400), new KeyValue(stage.opacityProperty(), 1.0))
        );
        // 停止已有动画,避免叠加
        timeline.stop();
        timeline.play();
    }

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

3. 边框颜色闪烁实现

这种方式更接近原生Dialog的警示效果,通过改变窗口边框颜色实现:

import javafx.animation.KeyFrame;
import javafx.animation.KeyValue;
import javafx.animation.Timeline;
import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.control.Label;
import javafx.stage.Modality;
import javafx.stage.Stage;
import javafx.stage.WindowEvent;
import javafx.util.Duration;

public class ModalBorderFlashDemo extends Application {

    private static final String NORMAL_BORDER_STYLE = "-fx-border-color: #cccccc; -fx-border-width: 2px;";
    private static final String ALERT_BORDER_STYLE = "-fx-border-color: #ff4444; -fx-border-width: 2px;";

    @Override
    public void start(Stage primaryStage) {
        primaryStage.setTitle("主窗口");
        primaryStage.setScene(new Scene(new Label("点击我试试"), 300, 200));
        primaryStage.show();

        Stage modalStage = new Stage();
        modalStage.initModality(Modality.APPLICATION_MODAL);
        modalStage.setTitle("模态窗口");
        // 给模态窗口设置初始边框
        Scene modalScene = new Scene(new Label("我是模态窗口"), 200, 100);
        modalScene.setStyle(NORMAL_BORDER_STYLE);
        modalStage.setScene(modalScene);

        modalStage.addEventHandler(WindowEvent.WINDOW_FOCUS_REQUESTED, event -> flashByBorder(modalScene));

        modalStage.show();
    }

    private void flashByBorder(Scene scene) {
        Timeline timeline = new Timeline(
                new KeyFrame(Duration.ZERO, new KeyValue(scene.styleProperty(), NORMAL_BORDER_STYLE)),
                new KeyFrame(Duration.millis(100), new KeyValue(scene.styleProperty(), ALERT_BORDER_STYLE)),
                new KeyFrame(Duration.millis(200), new KeyValue(scene.styleProperty(), NORMAL_BORDER_STYLE)),
                new KeyFrame(Duration.millis(300), new KeyValue(scene.styleProperty(), ALERT_BORDER_STYLE)),
                new KeyFrame(Duration.millis(400), new KeyValue(scene.styleProperty(), NORMAL_BORDER_STYLE))
        );
        timeline.stop();
        timeline.play();
    }

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

注意事项

  • 动画播放前调用timeline.stop()可以避免多次触发时动画叠加,确保每次闪烁都是独立完成的。
  • 如果需要调整闪烁的速度或次数,只需修改Timeline中的KeyFrame时间点和数量即可。

内容的提问来源于stack exchange,提问作者Calvin_Z

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.17 08:54:56