本示例创建一个类似于QLabel的小部件,如果文本太长而无法适合小部件的几何形状,则该小部件将以省略号的方式隐藏最后一条的可见行。
本示例ElidedLabel类是其实现核心,如果文本超出设定的矩形范围,则省略最后一条可见行。
ElidedLabel类定义
像QLabel一样,它ElidedLabel继承自QFrame。这是ElidedLabel该类的定义:
代码语言:javascript复制class ElidedLabel : public QFrame
{
Q_OBJECT
Q_PROPERTY(QString text READ text WRITE setText)
Q_PROPERTY(bool isElided READ isElided)
public:
explicit ElidedLabel(const QString &text, QWidget *parent = nullptr);
void setText(const QString &text);
const QString & text() const { return content; }
bool isElided() const { return elided; }
protected:
void paintEvent(QPaintEvent *event) override;
signals:
void elisionChanged(bool elided);
private:
bool elided;
QString content;
};
isElided
属性取决于窗口小部件的字体,文本内容和几何形状。每当这些更改中的任何一个发生时,elisionChanged()
信号都可能触发。我们将当前的elided
值缓存起来,这样就不必每次都要求重新计算它。
ElidedLabel类的实现
除了初始化成员变量外,构造函数还将大小策略设置为水平扩展,因为这是为了填充其容器的宽度并垂直增长。
代码语言:javascript复制ElidedLabel::ElidedLabel(const QString &text, QWidget *parent)
: QFrame(parent)
, elided(false)
, content(text)
{
setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Preferred);
}
设置文本的同时请求重绘小部件。
代码语言:javascript复制void ElidedLabel::setText(const QString &newText)
{
content = newText;
update();
}
在paintEvent()
中使用QTextLayout
将内容划分为几行,这些行环绕在单词边界上。除最后一个可见行外,每行均在上一行下方绘制lineSpacing
像素。QTextLine
的draw()
方法将使用坐标点作为左上角来绘制线条。
void ElidedLabel::paintEvent(QPaintEvent *event)
{
QFrame::paintEvent(event);
0
QPainter painter(this);
QFontMetrics fontMetrics = painter.fontMetrics();
bool didElide = false;
int lineSpacing = fontMetrics.lineSpacing();
int y = 0;
QTextLayout textLayout(content, painter.font());
textLayout.beginLayout();
forever {
QTextLine line = textLayout.createLine();
if (!line.isValid())
break;
line.setLineWidth(width());
int nextLineY = y lineSpacing;
if (height() >= nextLineY lineSpacing) {
line.draw(&painter, QPoint(0, y));
y = nextLineY;
可是,QTextLayout
不会忽略文本,因此必须以不同的方式对待最后一个可见行。如果最后一行太宽,则将其删除。QPainter
的drawText()
方法从基线开始绘制文本,该基线是最后绘制的线条下方的ascecnt()
像素。
最后,再创建一行以查看所有内容是否都适合该行。
代码语言:javascript复制} else {
QString lastLine = content.mid(line.textStart());
QString elidedLastLine = fontMetrics.elidedText(lastLine, Qt::ElideRight, width());
painter.drawText(QPoint(0, y fontMetrics.ascent()), elidedLastLine);
line = textLayout.createLine();
didElide = line.isValid();
break;
}
}
textLayout.endLayout();
关于更多
- 在QtCreator软件可以找到:
- 或在以下Qt安装目录找到:
C:Qt{你的Qt版本}Examples{你的Qt版本}widgetswidgetselidedlabel
- 相关链接
https://doc.qt.io/qt-5/qtwidgets-widgets-elidedlabel-example.html