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; + } +}