QLabel设置富文本,过长用省略号显示的方法
目录
1.背景
2.QFontMetrics
2.1.基本介绍
2.2.核心方法
2.3.使用注意
3.解决方法
3.1.简单方案:固定汉字数量截断(超过 N 字显示…)
3.2.推荐方案:按 Label 宽度自动省略(更美观)
1.背景
QLabel 设置 ** 富文本(HTML)** 时,原生的setElideMode会失效,无法像纯文本那样自动显示省略号;同时汉字是可变宽度,不能单纯按固定字数判断,更合理的是按「控件宽度」自动截断。
2.QFontMetrics
QFontMetrics是 Qt 中计算字体渲染实际尺寸的核心类,用来精准获取文本 / 字符在屏幕上的像素宽度、高度、行间距、省略文本等,解决「文本过长显示省略号」「文本居中 / 对齐」「自适应布局」等 UI 文本问题。它基于具体字体 + 字号 + 屏幕 DPI计算,不是按字符数估算,结果是实际渲染像素值,这也是它比「固定字数截断」更精准的原因。
2.1.基本介绍
1.作用
计算指定字体下:
- 单个字符 / 整段文本的宽度、高度
- 文本行高、基线、间距
- 文本超出宽度时自动生成带省略号的文本
- 文本占据的矩形区域
2.构造方式
// 1. 从指定字体构造 QFont font("Microsoft YaHei", 12); QFontMetrics fm(font); // 2. 直接用控件的字体(最常用) QFontMetrics fm(ui->label->font()); // 3. 高分屏/浮点精度(推荐高DPI屏幕使用) QFontMetricsF fmf(ui->label->font());3.QFontMetrics vs QFontMetricsF
QFontMetrics:整数像素,普通屏幕够用QFontMetricsF:浮点精度,高分屏(2K/4K/Retina)必须用,避免尺寸偏差
2.2.核心方法
1.文本宽度计算(最常用)
int width(const QString &text) const
计算文本渲染后的实际像素宽度,自动区分汉字、英文、符号(宽度不同)。
QString text = "你好Qt123"; int w = fm.width(text); // 得到该文本实际占多少像素
QRect boundingRect(const QString &text) const
返回文本渲染后占据的矩形区域(x/y/ 宽 / 高)。
QRect rect = fm.boundingRect("测试文本"); int textWidth = rect.width(); int textHeight = rect.height();2.自动省略超长文本
QString elidedText( const QString &text, Qt::TextElideMode mode, int width, int flags = 0 ) const自动截断文本并添加省略号,是 QLabel 省略显示的核心方法。
参数说明
text:原始文本mode:省略位置Qt::ElideRight:末尾省略(最常用,如「文本太长…」)Qt::ElideLeft:开头省略(… 本太长)Qt::ElideMiddle:中间省略(文… 长)Qt::ElideNone:不省略
width:允许的最大像素宽度flags:文本标志(默认 0 即可,单行文本)
使用示例
QString rawText = "这是一段非常非常长的需要显示省略号的文本"; // 最大宽度200px,末尾加省略号 QString elided = fm.elidedText(rawText, Qt::ElideRight, 200); ui->label->setText(elided);3.字体行高 / 高度相关
①
int height() const
字体总高度(字符最高点到最低点)。
②
int lineSpacing() const
推荐行高(换行后两行文本的间距)。
③
int ascent() const
基线到字符顶部的距离。
④
int descent() const
基线到字符底部的距离(如 g、y 的下延部分)。
int h = fm.height(); // 字体总高度 int spacing = fm.lineSpacing(); // 行间距4.字符基础尺寸
int minWidth():字体中最窄字符宽度int maxWidth():字体中最宽字符宽度int charWidth(QChar ch):单个字符的宽度
2.3.使用注意
1.宽度≠字符数
汉字≈2 个英文字符宽度,不同字体 / 字号宽度不同,绝对不能用字符数代替像素宽度。
2.控件宽度要留边距
计算时用label->width() - 间距,否则会紧贴边框。
int maxW = ui->label->width() - 4; // 左右各留2px边距3.富文本必须先转纯文本
HTML 标签不占渲染宽度,需先去除标签再计算:
QString plain = richText.remove(QRegularExpression("<[^>]+>"));4.控件大小变化时重算
窗口拉伸后 label 宽度改变,需在resizeEvent中重新计算省略文本。
3.解决方法
3.1.简单方案:固定汉字数量截断(超过 N 字显示…)
适合你明确要限制多少个汉字的场景,直接判断长度后拼接省略号,再套富文本。
#include <QLabel> #include <QString> // 示例:超过20个汉字就截断+省略号 QString richText = "<span style='color:red; font-size:14px;'>这里是很长的富文本内容...</span>"; // 提取纯文本长度(去掉HTML标签) QString plainText = richText.remove(QRegularExpression("<[^>]+>")); const int maxLen = 20; if (plainText.length() > maxLen) { // 截断后加省略号 QString showText = plainText.left(maxLen) + "..."; // 重新包装成富文本 ui->label->setText(QString("<span style='color:red; font-size:14px;'>%1</span>").arg(showText)); } else { ui->label->setText(richText); }3.2.推荐方案:按 Label 宽度自动省略(更美观)
#include <QFontMetrics> #include <QRegularExpression> // 通用设置带省略号的富文本 void setElidedLabel(QLabel *label, const QString &richText) { if(!label) return; // 1. 关闭换行 label->setWordWrap(false); // 2. 提取纯文本 QString plain = richText.remove(QRegularExpression("<[^>]+>")); // 3. 计算最大宽度(减去边距) QFontMetrics fm(label->font()); int maxWidth = label->width() - 4; // 4. 生成省略文本 QString elided = fm.elidedText(plain, Qt::ElideRight, maxWidth); // 5. 重新套回富文本样式 label->setText(QString("<span style='color:#333;'>%1</span>").arg(elided)); } // 窗口/控件resize时调用,适配宽度变化 void Widget::resizeEvent(QResizeEvent *event) { QWidget::resizeEvent(event); setElidedLabel(ui->label, "<b>超长富文本内容测试</b>"); }关键说明:
1.原生不支持原因:Qt::ElideRight只对纯文本生效,一旦用setTextFormat(Qt::RichText)或传入 HTML,省略号自动失效。
2.单行显示前提:记得关闭换行
label->setWordWrap(false); label->setAlignment(Qt::AlignLeft | Qt::AlignVCenter);