Qt 核心功能(17):自定义类型示例【官翻】

本文介绍了如何在Qt中创建并使用自定义类型。通过一个简单的Message类示例,展示了如何使其与Qt元对象系统集成,包括使用QVariant进行存储和检索的方法。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

自定义类型的示例

自定义类型示例展示了如何将自定义类型集成到Qt的元对象系统中。

概述

Qt提供了一系列标准值类型,用于提供丰富而有意义的api。这些类型与元对象系统集成,使它们能够存储在QVariant对象中,在调试信息中写入,并在信号槽通信中在组件之间发送。

定制类型也可以与元对象系统集成,只要它们的编写遵循一些简单的指导原则。在这个示例中,我们介绍了一个简单的Message类,描述了如何使它与QVariant一起工作,并展示了如何扩展它以生成其自身的可打印表示,以便在调试输出时使用。

Message类定义

Message类是一个简单的值类,它包含两条信息(QString和QStringList),每一条信息都可以使用简单的getter函数读取:

 class Message
 {
 public:
     Message() = default;
     ~Message() = default;
     Message(const Message &) = default;
     Message &operator=(const Message &) = default;

     Message(const QString &body, const QStringList &headers);

     QString body() const;
     QStringList headers() const;

 private:
     QString m_body;
     QStringList m_headers;
 };

如果要将类型集成到元对象系统中,则默认构造函数、复制构造函数和析构函数都是必需的,并且必须是公共的。除此之外,我们可以自由地实现任何需要的东西,以使类型做我们想做的事情,因此我们还包括一个构造函数,它允许我们设置类型的数据成员。

为了使类型能够与QVariant一起使用,我们使用Q_DECLARE_METATYPE()宏声明它:

 Q_DECLARE_METATYPE(Message);

我们不需要为这个宏编写任何额外的代码。

为了让我们看到每个消息对象发送到调试输出流时的可读描述,我们定义了一个流操作符:

QDebug operator<<(QDebug dbg, const Message &message);

如果您需要在代码中插入跟踪语句以进行调试,则此功能非常有用。

Message类实现

流操作符的实现方式如下:

 QDebug operator<<(QDebug dbg, const Message &message)
 {
     const QString body = message.body();
     QVector<QStringRef> pieces = body.splitRef(QLatin1String("\r\n"), Qt::SkipEmptyParts);
     if (pieces.isEmpty())
         dbg.nospace() << "Message()";
     else if (pieces.size() == 1)
         dbg.nospace() << "Message(" << pieces.first() << ")";
     else
         dbg.nospace() << "Message(" << pieces.first() << " ...)";
     return dbg.maybeSpace();
 }

在这里,我们希望根据消息体中存储的行数来表示每个值。我们将文本流化为传递给运算符的QDebug对象,并返回从其成员函数maybeSpace()中获得的QDebug对象;这在创建自定义Qt类型文档中有更详细的描述。

为了完整性,我们包括了getter函数的代码:

 QString Message::body() const
 {
     return m_body;
 }

 QStringList Message::headers() const
 {
     return m_headers;
 }

类型被完全定义、实现并与元对象系统集成后,我们现在就可以使用它了。

使用Message类

在示例的main()函数中,我们展示了如何将消息对象发送到调试流,从而将其打印到控制台:

     Message message(body, headers);
     qDebug() << "Original:" << message;

您可以用与使用标准Qt值类型完全相同的方式对QVariant使用该类型。下面是如何使用QVariant::setValue()函数存储一个值:

     QVariant stored;
     stored.setValue(message);

另外,如果使用不支持成员模板函数的编译器,也可以使用QVariant::fromValue()函数。
值可以使用QVariant::value()成员模板函数检索:

    Message retrieved = qvariant_cast<Message>(stored);
    qDebug() << "Retrieved:" << retrieved;
    retrieved = stored.value<Message>();
    qDebug() << "Retrieved:" << retrieved;

进一步阅读

定义消息类型还可以与直接信号槽连接一起使用。

若要注册一个自定义类型以与排队信号和槽(例如在跨线程通信中使用的那些)一起使用,请参阅排队自定义类型示例。

关于在Qt中使用自定义类型的更多信息可以在创建自定义Qt类型文档中找到。

完整代码

#include <QtCore>
#include <QtGui>
#include <QtWidgets>

class Message
{
public:
    Message() = default;
    ~Message() = default;
    Message(const Message &) = default;
    Message &operator=(const Message &) = default;

    Message(const QString &body, const QStringList &headers)
        : m_body(body), m_headers(headers)    {    }

    QString body() const
    {   return m_body;  }

    QStringList headers() const
    {   return m_headers;   }

private:
    QString m_body;
    QStringList m_headers;
};
Q_DECLARE_METATYPE(Message);

QDebug operator<<(QDebug dbg, const Message &message)
{
    const QString body = message.body();
    QVector<QStringRef> pieces = body.splitRef(QLatin1String("\r\n"), Qt::SkipEmptyParts);
    if (pieces.isEmpty())
        dbg.nospace() << "Message()";
    else if (pieces.size() == 1)
        dbg.nospace() << "Message(" << pieces.first() << ")";
    else
        dbg.nospace() << "Message(" << pieces.first() << " ...)";
    return dbg.maybeSpace();
}

int main(int argc, char *argv[])
{
    QApplication a(argc,argv);
    QStringList headers;
    headers << "Subject: Hello World"
            << "From: address@example.com";
    QString body = "This is a test.\r\nThat is an other test.\r\n";

    Message message(body, headers);
    qDebug() << "Original:" << message;

    QVariant stored;
    stored.setValue(message);

    qDebug() << "Stored:" << stored;

    Message retrieved = qvariant_cast<Message>(stored);
    qDebug() << "Retrieved:" << retrieved;
    retrieved = stored.value<Message>();
    qDebug() << "Retrieved:" << retrieved;

    a.exec();
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值