diff --git a/src/main/java/com/imyeyu/fx/ui/components/LabelTips.java b/src/main/java/com/imyeyu/fx/ui/components/LabelTips.java new file mode 100644 index 0000000..52ec941 --- /dev/null +++ b/src/main/java/com/imyeyu/fx/ui/components/LabelTips.java @@ -0,0 +1,313 @@ +package com.imyeyu.fx.ui.components; + +import com.imyeyu.fx.ui.TimiFXUI; +import com.imyeyu.utils.Time; +import javafx.animation.PauseTransition; +import javafx.application.Platform; +import javafx.beans.property.LongProperty; +import javafx.beans.property.SimpleLongProperty; +import javafx.scene.control.Label; +import javafx.scene.paint.Paint; +import javafx.util.Duration; + +/** + * 提示标签,可以临时显示提示内容,经过指定时间后自动恢复原内容。 + *
+ * 此组件是线程安全的,可以从任意线程调用 {@link #tips(String)} 方法。 + * 如果在提示期间再次调用 tips 方法,会重置计时器并显示新的提示内容, + * 恢复时仍然恢复为最初的原始内容。 + *
+ * + *{@code
+ * LabelTips label = new LabelTips("默认内容");
+ * label.tips("操作成功!"); // 使用默认 3 秒
+ * label.tips("保存完成!", 5000); // 指定 5 秒
+ * }
+ *
+ * @author 夜雨
+ * @since 2025-01-14
+ */
+public class LabelTips extends Label implements TimiFXUI.Colorful {
+
+ /** 默认提示持续时间(毫秒) */
+ public static final long DEFAULT_DURATION = Time.S * 5;
+
+ /** 信息提示颜色 */
+ public static final Paint INFO_TEXT_FILL = BLUE;
+
+ /** 警告提示颜色 */
+ public static final Paint WARN_TEXT_FILL = ORANGE;
+
+ /** 错误提示颜色 */
+ public static final Paint ERROR_TEXT_FILL = RED;
+
+ /** 提示持续时间(毫秒) */
+ protected LongProperty duration;
+
+ /** 原始内容,提示结束后恢复 */
+ private volatile String originalText;
+
+ /** 原始颜色,提示结束后恢复 */
+ private volatile Paint originalTextFill;
+
+ /** 定时器,用于恢复原内容 */
+ private PauseTransition transition;
+
+ /** 同步锁 */
+ private final Object lock = new Object();
+
+ /** 默认构造器 */
+ public LabelTips() {
+ this("");
+ }
+
+ /**
+ * 标准构造器
+ *
+ * @param text 标签初始文本
+ */
+ public LabelTips(String text) {
+ super(text);
+ this.duration = new SimpleLongProperty(DEFAULT_DURATION);
+ }
+
+ /**
+ * 显示提示内容,使用默认持续时间
+ *
+ * @param content 提示内容
+ */
+ public void tips(String content) {
+ tips(content, duration.get());
+ }
+
+ /**
+ * 显示提示内容,指定持续时间
+ *
+ * @param content 提示内容
+ * @param millis 持续时间(毫秒)
+ */
+ public void tips(String content, long millis) {
+ tips(content, Duration.millis(millis));
+ }
+
+ /**
+ * 显示提示内容,指定持续时间
+ *
+ * @param content 提示内容
+ * @param duration 持续时间
+ */
+ public void tips(String content, Duration duration) {
+ tips(content, duration, null);
+ }
+
+ /**
+ * 显示提示内容,指定持续时间与颜色
+ *
+ * @param content 提示内容
+ * @param duration 持续时间
+ * @param textFill 文本颜色
+ */
+ public void tips(String content, Duration duration, Paint textFill) {
+ if (Platform.isFxApplicationThread()) {
+ doTips(content, duration, textFill);
+ } else {
+ Platform.runLater(() -> doTips(content, duration, textFill));
+ }
+ }
+
+ /**
+ * 显示信息提示内容,使用默认持续时间
+ *
+ * @param content 提示内容
+ */
+ public void info(String content) {
+ info(content, duration.get());
+ }
+
+ /**
+ * 显示信息提示内容,指定持续时间
+ *
+ * @param content 提示内容
+ * @param millis 持续时间(毫秒)
+ */
+ public void info(String content, long millis) {
+ info(content, Duration.millis(millis));
+ }
+
+ /**
+ * 显示信息提示内容,指定持续时间
+ *
+ * @param content 提示内容
+ * @param duration 持续时间
+ */
+ public void info(String content, Duration duration) {
+ tips(content, duration, INFO_TEXT_FILL);
+ }
+
+ /**
+ * 显示警告提示内容,使用默认持续时间
+ *
+ * @param content 提示内容
+ */
+ public void warn(String content) {
+ warn(content, duration.get());
+ }
+
+ /**
+ * 显示警告提示内容,指定持续时间
+ *
+ * @param content 提示内容
+ * @param millis 持续时间(毫秒)
+ */
+ public void warn(String content, long millis) {
+ warn(content, Duration.millis(millis));
+ }
+
+ /**
+ * 显示警告提示内容,指定持续时间
+ *
+ * @param content 提示内容
+ * @param duration 持续时间
+ */
+ public void warn(String content, Duration duration) {
+ tips(content, duration, WARN_TEXT_FILL);
+ }
+
+ /**
+ * 显示错误提示内容,使用默认持续时间
+ *
+ * @param content 提示内容
+ */
+ public void error(String content) {
+ error(content, duration.get());
+ }
+
+ /**
+ * 显示错误提示内容,指定持续时间
+ *
+ * @param content 提示内容
+ * @param millis 持续时间(毫秒)
+ */
+ public void error(String content, long millis) {
+ error(content, Duration.millis(millis));
+ }
+
+ /**
+ * 显示错误提示内容,指定持续时间
+ *
+ * @param content 提示内容
+ * @param duration 持续时间
+ */
+ public void error(String content, Duration duration) {
+ tips(content, duration, ERROR_TEXT_FILL);
+ }
+
+ /**
+ * 执行提示逻辑,必须在 FX 线程调用
+ *
+ * @param content 提示内容
+ * @param duration 持续时间
+ */
+ private void doTips(String content, Duration duration, Paint textFill) {
+ synchronized (lock) {
+ // 停止之前的定时器
+ if (transition != null) {
+ transition.stop();
+ }
+
+ // 仅在首次调用时保存原始内容
+ if (originalText == null) {
+ originalText = getText();
+ originalTextFill = getTextFill();
+ }
+
+ // 设置提示内容
+ setText(content);
+ if (textFill != null) {
+ setTextFill(textFill);
+ } else {
+ setTextFill(originalTextFill);
+ }
+
+ // 创建定时器
+ transition = new PauseTransition(duration);
+ transition.setOnFinished(e -> {
+ synchronized (lock) {
+ setText(originalText);
+ setTextFill(originalTextFill);
+ originalText = null;
+ originalTextFill = null;
+ transition = null;
+ }
+ });
+ transition.play();
+ }
+ }
+
+ /**
+ * 立即恢复原始内容,取消正在进行的提示
+ */
+ public void restore() {
+ if (Platform.isFxApplicationThread()) {
+ doRestore();
+ } else {
+ Platform.runLater(this::doRestore);
+ }
+ }
+
+ /**
+ * 执行恢复逻辑,必须在 FX 线程调用
+ */
+ private void doRestore() {
+ synchronized (lock) {
+ if (transition != null) {
+ transition.stop();
+ transition = null;
+ }
+ if (originalText != null) {
+ setText(originalText);
+ setTextFill(originalTextFill);
+ originalText = null;
+ originalTextFill = null;
+ }
+ }
+ }
+
+ /**
+ * 检查当前是否正在显示提示
+ *
+ * @return 如果正在显示提示返回 true
+ */
+ public boolean isTipping() {
+ synchronized (lock) {
+ return originalText != null;
+ }
+ }
+
+ /**
+ * 获取默认提示持续时间
+ *
+ * @return 持续时间(毫秒),默认 {@value #DEFAULT_DURATION}
+ */
+ public long getDuration() {
+ return duration.get();
+ }
+
+ /**
+ * 设置默认提示持续时间
+ *
+ * @param millis 持续时间(毫秒)
+ */
+ public void setDuration(long millis) {
+ this.duration.set(millis);
+ }
+
+ /**
+ * 获取持续时间属性
+ *
+ * @return 持续时间属性
+ */
+ public LongProperty durationProperty() {
+ return duration;
+ }
+}