feat: add info/warn/error methods to LabelTips

This commit is contained in:
Timi
2026-01-14 14:57:13 +08:00
parent 68f39aa834
commit 6837781383

View File

@ -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;
/**
* 提示标签,可以临时显示提示内容,经过指定时间后自动恢复原内容。
* <p>
* 此组件是线程安全的,可以从任意线程调用 {@link #tips(String)} 方法。
* 如果在提示期间再次调用 tips 方法,会重置计时器并显示新的提示内容,
* 恢复时仍然恢复为最初的原始内容。
* </p>
*
* <pre>{@code
* LabelTips label = new LabelTips("默认内容");
* label.tips("操作成功!"); // 使用默认 3 秒
* label.tips("保存完成!", 5000); // 指定 5 秒
* }</pre>
*
* @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;
}
}