首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Qt官方示例-文本对象

Qt官方示例-文本对象

作者头像
Qt君
发布2023-03-17 13:38:50
1.2K0
发布2023-03-17 13:38:50
举报
文章被收录于专栏:跟Qt君学编程跟Qt君学编程

❝文本对象示例演示如何将SVG文件插入QTextDocument中。❞

  QTextDocument包括元素,如文本块和帧的层次结构的。文本对象描述了一个或多个这些元素的结构或格式。例如,从HTML导入的图像是使用文本对象实现的。文档的布局使用文本对象来布局和渲染(绘制)文档。每个对象都知道如何绘制它们控制的元素,并计算其大小。

  为了能够在文本文档中插入SVG图像,我们创建了一个文本对象,并对该对象进行绘画。然后可以在QTextCharFormat上设置此对象。我们还将文本对象注册到文档的布局中,从而使其能够绘制受文本对象控制的QTextCharFormat。我们可以通过以下步骤总结该过程:

  • 实现文本对象。
  • 用文本文档的布局注册文本对象。
  • 将文本对象设置在QTextCharFormat上。
  • 将具有该文本字符格式的QChar::ObjectReplacementCharacter插入文档中。

  该示例包含以下类:

  • SvgTextObject 实现文本对象。
  • Window显示了可以插入SVG图像的QTextEdit。

SvgTextObject类定义

  让我们看一下的头文件SvgTextObject:

class SvgTextObject : public QObject, public QTextObjectInterface
{
    Q_OBJECT
    Q_INTERFACES(QTextObjectInterface)

public:
    QSizeF intrinsicSize(QTextDocument *doc, int posInDocument,
                         const QTextFormat &format) override;
    void drawObject(QPainter *painter, const QRectF &rect, QTextDocument *doc,
                    int posInDocument, const QTextFormat &format) override;
};

  文本对象是实现QTextObjectInterface的QObject。请注意,继承的第一个类必须是QObject,并且必须使用Q_INTERFACES来让Qt知道您的类实现了QTextObjectInterface。

  文档布局保留了存储为QObject的文本对象的集合,每个文本对象都具有关联的对象类型。布局将关联对象类型的QObject强制转换为QTextObjectInterface。

  所述intrinsicSize和drawObject函数然后用来计算文本对象的大小和绘制。

SvgTextObject类的实现

  我们首先看一下internalSize函数:

QSizeF SvgTextObject::intrinsicSize(QTextDocument * /*doc*/, int /*posInDocument*/,
                                    const QTextFormat &format)
{
    QImage bufferedImage = qvariant_cast<QImage>(format.property(Window::SvgData));
    QSize size = bufferedImage.size();

    if (size.height() > 25)
        size *= 25.0 / (double) size.height();

    return QSizeF(size);
}

  intrinsicSize()由布局调用以计算文本对象的大小。注意,我们已经在QImage上绘制了SVG图像。这是因为SVG渲染非常耗时。如果我们每次都使用QSvgRenderer绘制大型图像,该示例将严重滞后卡顿。

void SvgTextObject::drawObject(QPainter *painter, const QRectF &rect,
                               QTextDocument * /*doc*/, int /*posInDocument*/,
                               const QTextFormat &format)
{
    QImage bufferedImage = qvariant_cast<QImage>(format.property(Window::SvgData));

    painter->drawImage(rect, bufferedImage);
}

  在drawObject()中,我们使用布局提供的QPainter绘制SVG图像。

窗口类定义

「Window」类是具有一个独立的窗口的QTextEdit其中SVG图像可以被插入。

class Window : public QWidget
{
    Q_OBJECT

public:
    enum { SvgTextFormat = QTextFormat::UserObject + 1 };
    enum SvgProperties { SvgData = 1 };

    Window();

private slots:
    void insertTextObject();

private:
    void setupTextObject();
    void setupGui();

private:
    QTextEdit *textEdit;
    QLabel *fileNameLabel;
    QLineEdit *fileNameLineEdit;
    QPushButton *insertTextObjectButton;
};

  该insertTextObject()槽函数在当前光标位置插入一个SVG图像,同时setupTextObject()创建并使用文本编辑文档的布局注册SvgTextObject。

  构造函数只需调用setupTextObject()和setupGui()创建和布局窗口。

窗口类的实现

  现在,从setupTextObject()开始,我们将仔细研究与文本对象相关的功能。

void Window::setupTextObject()
{
    QObject *svgInterface = new SvgTextObject;
    svgInterface->setParent(this);
    textEdit->document()->documentLayout()->registerHandler(SvgTextFormat, svgInterface);
}

  SvgTextFormat的值是我们的对象类型的数量。它用于通过文档布局识别对象类型。

  请注意,我们仅创建一个SvgTextObject实例。它将用于具有对象类型的所有QTextCharFormatSvgTextFormat。

  让我们看看insertTextObject()功能:

void Window::insertTextObject()
{
    QString fileName = fileNameLineEdit->text();
    QFile file(fileName);
    if (!file.open(QIODevice::ReadOnly)) {
        QMessageBox::warning(this, tr("Error Opening File"),
                             tr("Could not open '%1'").arg(fileName));
    }

    QByteArray svgData = file.readAll();

  首先,.svg打开文件并将其内容读入svgData数组。

    QTextCharFormat svgCharFormat;
    svgCharFormat.setObjectType(SvgTextFormat);
    QSvgRenderer renderer(svgData);

    QImage svgBufferImage(renderer.defaultSize(), QImage::Format_ARGB32);
    QPainter painter(&svgBufferImage);
    renderer.render(&painter, svgBufferImage.rect());

    svgCharFormat.setProperty(SvgData, svgBufferImage);

    QTextCursor cursor = textEdit->textCursor();
    cursor.insertText(QString(QChar::ObjectReplacementCharacter), svgCharFormat);
    textEdit->setTextCursor(cursor);
}

  为了加快速度,我们将SVG图像缓存在QImage中。我们使用setProperty()将QImage存储在QTextCharFormat中。我们稍后可以使用property()获取它。

  我们使用QTextCursor以标准方式插入字符格式。注意,我们使用特殊的QChar对象替换字符(https://doc.qt.io/qt-5/qchar.html#SpecialCharacter-enum)。

关于更多

  • 「QtCreator软件」可以找到:
  • 或在以下「Qt安装目录」找到:
C:\Qt\{你的Qt版本}\Examples\{你的Qt版本}\svg\richtext\textobject
  • 「相关链接」
https://doc.qt.io/qt-5/qtsvg-richtext-textobject-example.html
本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2020-08-30,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 Qt君 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • SvgTextObject类定义
  • SvgTextObject类的实现
  • 窗口类定义
  • 窗口类的实现
  • 关于更多
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档