Qt Core

Qt核心模块将这些特性添加到c++中:

The Meta-Object System

Qt的元对象系统为对象间通信、运行时类型信息和动态属性系统提供了信号和插槽机制。
元对象系统基于以下三点:

  1. QObject类为可以利用元对象系统的对象提供了一个基类。
  2. 类声明的私有部分中的Q_OBJECT宏用于启用元对象特性,例如动态属性、信号和槽。
  3. 元对象编译器(moc)为每个QObject子类提供实现元对象特性所需的代码。

QMetaObject *QObject::metaObject()

className():

QObject *obj = new QPushButton;
obj->metaObject()->className();             // returns "QPushButton"

QPushButton::staticMetaObject.className();  // returns "QPushButton"

inherits():

QTimer *timer = new QTimer;         // QTimer inherits QObject
timer->inherits("QTimer");          // returns true
timer->inherits("QObject");         // returns true
timer->inherits("QAbstractButton"); // returns false

// QVBoxLayout inherits QObject and QLayoutItem
QVBoxLayout *layout = new QVBoxLayout;
layout->inherits("QObject");        // returns true
layout->inherits("QLayoutItem");    // returns true (even though QLayoutItem is not a QObject)

qobject_cast():

QObject *obj = new MyWidget;
QWidget *widget = qobject_cast<QWidget *>(obj);
MyWidget *myWidget = qobject_cast<MyWidget *>(obj);
QLabel *label = qobject_cast<QLabel *>(obj);
    // label is 0

The Property System

要声明一个属性,在继承QObject的类中使用Q_PROPERTY()宏。
下面是取自类QWidget的属性声明的一些典型示例:

Q_PROPERTY(bool focus READ hasFocus)
Q_PROPERTY(bool enabled READ isEnabled WRITE setEnabled)
Q_PROPERTY(QCursor cursor READ cursor WRITE setCursor RESET unsetCursor)

下面是一个示例,展示了如何使用member关键字将成员变量导出为Qt属性。注意,必须指定NOTIFY信号才能允许QML属性绑定。

    Q_PROPERTY(QColor color MEMBER m_color NOTIFY colorChanged)
    Q_PROPERTY(qreal spacing MEMBER m_spacing NOTIFY spacingChanged)
    Q_PROPERTY(QString text MEMBER m_text NOTIFY textChanged)
    ...
signals:
    void colorChanged();
    void spacingChanged();
    void textChanged(const QString &newText);

private:
    QColor  m_color;
    qreal   m_spacing;
    QString m_text;

accessor function:
READ 如果没有指定成员变量,则需要READ访问器函数。它用于读取属性值。理想情况下,为此目的使用const函数,它必须返回属性的类型或对该类型的const引用。
WRITE 访问器函数是可选的。用于设置属性值。它必须返回void,并且必须只有一个参数,要么是属性的类型,要么是指向该类型的指针或引用。例如,QWidget::enabled具有WRITE功能QWidget::setEnabled()。只读属性不需要WRITE函数。
MEMBER 给定的成员变量可读可写,而不需要创建READ和WRITE访问器函数。如果需要控制变量访问,除了成员变量关联之外,还可以使用READ或WRITE访问器函数(但不能两者都使用)。
RESET 是可选的,它用于将属性设置回其上下文特定的默认值。例如,QWidget::cursor具有典型的READ和WRITE函数,QWidget::cursor()和QWidget::setCursor(),并且它还有一个RESET函数,QWidget::unsetCursor(),因为没有调用QWidget::setCursor()可以意味着重置到特定于上下文的光标。RESET函数必须返回void且不带参数。
NOTIFY 信号方法是可选的. 它需要在该类中指定一个现有的信号,每当属性的值发生变化时,该信号就会发出。

QObject::property() and QObject::setProperty() QMetaProperties

QPushButton *button = new QPushButton;
QObject *object = button;

button->setDown(true);
object->setProperty("down", true);

button->setProperty("flat",true);
QVariant isflat = button->property("flat");
qDebug() << isflat << endl;//QVariant(bool, true)
QObject *object = ...
const QMetaObject *metaobject = object->metaObject();
int count = metaobject->propertyCount();
for (int i=0; i<count; ++i) {
    QMetaProperty metaproperty = metaobject->property(i);
    const char *name = metaproperty.name();
    QVariant value = object->property(name);
    ...
}

A Simple Example:

class MyClass : public QObject
{
    Q_OBJECT
    Q_PROPERTY(Priority priority READ priority WRITE setPriority NOTIFY priorityChanged)

public:
    MyClass(QObject *parent = nullptr);
    ~MyClass();

    enum Priority { High, Low, VeryHigh, VeryLow };
    Q_ENUM(Priority)

    void setPriority(Priority priority)
    {
        m_priority = priority;
        emit priorityChanged(priority);
    }
    Priority priority() const
    { return m_priority; }

signals:
    void priorityChanged(Priority);

private:
    Priority m_priority;
};

有两种方法设置属性

MyClass *myinstance = new MyClass;
QObject *object = myinstance;

myinstance->setPriority(MyClass::VeryHigh);
object->setProperty("priority", "VeryHigh");

QObject::setProperty()也可用于在运行时为类的实例添加新属性。当使用名称和值调用它时,如果QObject中存在具有给定名称的属性,并且给定的值与属性的类型兼容,则该值将存储在属性中,并返回true。如果该值与属性的类型不兼容,则不会更改属性,并返回false。但是,如果具有给定名称的属性在QObject中不存在(即,如果它没有使用Q_PROPERTY()声明),则一个具有给定名称和值的新属性将自动添加到QObject中,但仍然返回false。这意味着不能使用返回false来确定是否实际设置了特定属性,除非您事先知道该属性已经存在于QObject中。

参考连接:
https://doc.qt.io/qt-6/qtcore-index.html

posted @ 2023-06-19 17:03  yg1990  阅读(42)  评论(0编辑  收藏  举报