Qt官方示例-文本省略

2023-03-17 14:31:54 浏览数 (2)

本示例创建一个类似于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像素。QTextLinedraw()方法将使用坐标点作为左上角来绘制线条。

代码语言:javascript复制
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不会忽略文本,因此必须以不同的方式对待最后一个可见行。如果最后一行太宽,则将其删除。QPainterdrawText()方法从基线开始绘制文本,该基线是最后绘制的线条下方的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安装目录找到:
代码语言:javascript复制
C:Qt{你的Qt版本}Examples{你的Qt版本}widgetswidgetselidedlabel
  • 相关链接
代码语言:javascript复制
https://doc.qt.io/qt-5/qtwidgets-widgets-elidedlabel-example.html

0 人点赞