zoukankan      html  css  js  c++  java
  • 解析Qt元对象系统(四) 属性系统(确实比较方便)

    官方解释

    我们在Qt源码中可以看到一个QObject的子类经常会用到一些Q_开头的宏,例如QMainWindow类开始部分代码是这样的:

    Q_PROPERTY(QSize iconSize READ iconSize WRITE setIconSize)
    Q_PROPERTY(Qt::ToolButtonStyle toolButtonStyle READ toolButtonStyle WRITE setToolButtonStyle)
    ......
    public:
    enum DockOption {
    AnimatedDocks = 0x01,
    AllowNestedDocks = 0x02,
    AllowTabbedDocks = 0x04,
    ForceTabbedDocks = 0x08, // implies AllowTabbedDocks, !AllowNestedDocks
    VerticalTabs = 0x10, // implies AllowTabbedDocks
    GroupedDragging = 0x20 // implies AllowTabbedDocks
    };
    Q_ENUM(DockOption)
    Q_DECLARE_FLAGS(DockOptions, DockOption)
    Q_FLAG(DockOptions)
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    这几个宏也不是标准C++的内容,它们属于Qt的属性系统,是元对象系统的一部分。使用属性系统的类必须是QObject的子类,还得包含宏Q_OBJECT。

    在标准C++中,为了保证封装性,我们经常声明一个私有变量,然后声明两个公有函数,即set函数和get函数。在Qt中我们可以使用宏Q_PROPERTY来实现这些,还包括信号的发射,后者实际是在set函数中实现的。

    Q_PROPERTY(type name
    READ getFunction
    [WRITE setFunction]
    [RESET resetFunction]
    [NOTIFY notifySignal] )

    Q_PROPERTY(type name
    MEMBER memberName
    [READ getFunction]
    [WRITE setFunction]
    [RESET resetFunction]
    [NOTIFY notifySignal] )
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    这是Q_PROPERTY的两种简单而常用的形式。

    type 是指属性的类型,可以是 C++ 标准类型、类名、结构体、枚举等
    name 属性的名字,仅仅是一个用于标识属性的名字,不是实际存在的成员变量
    READ 标出该属性的读函数 getFunction,Qt 属性的读函数通常省略 get 三个字母。
    WRITE 标出该属性的写函数 setFunction,中括号表示可选,写函数不是必须的。
    RESET 标出该属性的重置函数
    resetFunction,重置函数将属性设为某个默认值,中括号表示可选,重置函数不是必须的。
    NOTIFY 标出该属性变化时发出的通知信号 notifySignal,中括号表示可选,这个信号不是必须的。
    在明确标出属性使用的成员变量的情况下,属性的读写函数可以省略不写,Qt 的 moc 工具会自动为成员变量生成读写代码。比如:

    READ, WRITE以及RESET可以被继承,也可以是虚函数。property的类型可以是QVariant支持的任何类型,也可以是用户定义的类型,这就是Q_ENUM()的作用了。
    枚举类型必须用Q_ENUM()宏注册,这也是元对象系统的一部分,然后就可以使用QObject::setProperty(); 我们必须为READ和WRITE提供自己的声明。
    结合以上几条,我们这样写一个类:

    class MainWindow : public QMainWindow
    {
    Q_OBJECT
    Q_PROPERTY(int value MEMBER m_value NOTIFY valueChanged);
    Q_PROPERTY(Priority prioity MEMBER m_priority NOTIFY priChanged);
    public:
    MainWindow(QWidget* parent= nullptr);
    ~MainWindow();
    enum Priority{Low,High, VeryHigh};
    Q_ENUM(Priority);
    signals:
    void valueChanged();
    void priChanged();
    private:
    Ui::MainWindow* ui;
    int m_value;
    Priority m_priority;
    };
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    这样就可以在类外调用相关函数了:

    m.setProperty("value",15);
    m.setProperty("prioity",MainWindow::VeryHigh);

    qDebug()<<"value:"<<m.property("value").toInt();
    qDebug()<<"prioity value:"<<m.property("prioity").toInt();
    qDebug()<<m.dynamicPropertyNames();
    1
    2
    3
    4
    5
    6
    还有一个宏Q_FLAG(), 它与Q_ENUM()类似, 也是注册枚举类型, 但可以使用|操作。一个I/O类可能有枚举值Read和Write ,那么QObject::setProperty()就可以接受Read | Write。记得必须用Q_DECLARE_FLAGS完成注册

    还有一个宏Q_CLASSINFO(),在类的声明里添加类附加信息,比如:

    Q_CLASSINFO("Version", "1.0.0")
    1
    附加信息也是成对的“名称-值”,不过注意 名称和值 都是普通字符串。如果希望在运行时查询类的附加信息,可以先用 QObject::metaObject() 获取当前对象包含的元对象数据,然后使用 QMetaObject::​classInfo 函数查询某个序号的附加信息:

    //类内声明
    Q_CLASSINFO("Version", "1.0.0")
    Q_CLASSINFO("Author", "Winland")

    //类外使用
    //获取类的附加信息
    const QMetaObject *pMO = w.metaObject();

    //附加信息个数
    int nInfoCount = pMO->classInfoCount();

    //打印所有的附加信息
    for(int i=0; i<nInfoCount; i++)
    {
    QMetaClassInfo info = pMO->classInfo(i);
    qDebug()<<info.name()<<" "<<info.value();
    }
    ---------------------
    作者:SilentAssassin
    来源:CSDN
    原文:https://blog.csdn.net/yao5hed/article/details/81142358?utm_source=copy
    版权声明:本文为博主原创文章,转载请附上博文链接!

  • 相关阅读:
    UVa 10118 记忆化搜索 Free Candies
    CodeForces 568B DP Symmetric and Transitive
    UVa 11695 树的直径 Flight Planning
    UVa 10934 DP Dropping water balloons
    CodeForces 543D 树形DP Road Improvement
    CodeForces 570E DP Pig and Palindromes
    HDU 5396 区间DP 数学 Expression
    HDU 5402 模拟 构造 Travelling Salesman Problem
    HDU 5399 数学 Too Simple
    CodeForces 567F DP Mausoleum
  • 原文地址:https://www.cnblogs.com/findumars/p/9799974.html
Copyright © 2011-2022 走看看