Property system in Qt

Qt provides a very sophisticated property system that allows us to define both static properties during compilation using the Q_PROPERTY() macro, and allows us to add dynamic properties using the setProperty function.

The macro definition of Q_PROPERTY() is as follows:

Q_PROPERTY(type name
           (READ getFunction [WRITE setFunction] |
            MEMBER memberName [(READ getFunction | WRITE setFunction)])
           [RESET resetFunction]
           [NOTIFY notifySignal]
           [REVISION int]
           [DESIGNABLE bool]
           [SCRIPTABLE bool]
           [STORED bool]
           [USER bool]
           [CONSTANT]
           [FINAL])

Here are some brief introductions to markup:

  • READ tag: The READ tag is required if the MEMBER tag is not marked for the attribute. Declare a function that reads properties.
  • WRITE tag: optional configuration. Declare a function with optional properties, the specified function can only have one parameter, and the return value must be void.
  • MEMBER tag: If you do not specify the READ function for the attribute, you must associate a member variable with it, so that the member variable can be read and written without specifying the READ/WRITE function. Of course, if you want to control its reading and writing, you can also specify the READ/WRITE function.
  • RESET flag: optional configuration. The purpose of this function is to roll back a property to the default value that matches its context.
  • NOTIFY tag: optional configuration. Associate a signal with the property (the signal must be declared in the class), and the signal will be triggered when the value of the property changes. The NOTIFY signal specified for the MEMBER variable can have at most one parameter, and its type must match the type of the attribute. When the signal fires, its value is the value of the property.
  • REVISON tag: optional configuration. This tag is usually specified when exporting a property for use in QML, and it specifies the API version to which the property applies. The default value is 0.
  • DESIGNABLE flag: optional configuration. Used to indicate whether a property can be used by Qt Designer, the default value is true. You can also use a member function that returns a boolean value instead of true or false.
  • SCRIPTABLE tag: optional configuration. Used to indicate whether a property can be accessed by the script engine, the default value is true.
  • STORED marker: optional configuration. Indicates whether an attribute exists independently or is derived from other attribute values. The default value is true.
  • USER tag: optional configuration. Indicates whether a property is designed to be user-facing or user-editable. Generally, a class can only have one attribute marked as true by USER, and the default is false.
  • CONSTANT tag: optional configuration. Indicates that a property is constant. A property marked as constant cannot have the WRITE function and the NITIFY signal.
  • FINAL flag: optional configuration. Indicates that a property cannot be modified by derived classes. The moc tool does not check whether a property marked as FINAL true has been modified by a derived class, so implementers need to be careful not to modify it in derived classes.

Here is a simple example of property usage:
Code in .h file:

#ifndef WIDGET_H
#define WIDGET_H

#include <QWidget>
#include <QVBoxLayout>

class Widget : public QWidget
{
    Q_OBJECT

    Q_PROPERTY(int testProperty READ testProperty WRITE setTestProperty NOTIFY testPropertyChanged)

public:
    Widget(QWidget *parent = 0);
    ~Widget();

private:
    int m_TestProperty;
    int testProperty() const;
    void setTestProperty(int);

signals:
    void testPropertyChanged(int);
};

// ---------------------------------------------------------------------
class TestPropertyWidget : public QWidget
{
    Q_OBJECT

public:
    TestPropertyWidget(QWidget *parent = nullptr);
    ~TestPropertyWidget();

    Widget *getMainWidget(void){
        return m_Widget;
    }

private:
    Widget *m_Widget = nullptr;
};

#endif // WIDGET_H

Code in .cpp

#include "widget.h"
#include <QDebug>

Widget::Widget(QWidget *parent)
    : QWidget(parent)
{
    m_TestProperty = 10;
}

Widget::~Widget()
{

}

int Widget::testProperty() const
{
    return m_TestProperty;
}

void Widget::setTestProperty(int property)
{
    m_TestProperty = property;
    emit testPropertyChanged(property);
}

// ---------------------------------------------------------------------
TestPropertyWidget::TestPropertyWidget(QWidget *parent)
    :QWidget(parent)
{
    QVBoxLayout *m_MainLayout = new QVBoxLayout(this);

    m_Widget = new Widget;
    m_MainLayout->addWidget(m_Widget);

    QObject::connect(m_Widget, &Widget::testPropertyChanged, [&](int testPropertyValue)->void{
       qDebug() << "TestPropertyChanged " <<  testPropertyValue;
    });
}

TestPropertyWidget::~TestPropertyWidget()
{

}

The call in the main function:

#include "widget.h"
#include <QApplication>
#include <QObject>
#include <QDebug>

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
    TestPropertyWidget w;
    w.setGeometry(100, 100, 800, 600);
    w.show();

    qDebug() << w.getMainWidget()->property("testProperty").toInt();

    w.getMainWidget()->setProperty("testProperty", 20);


    return a.exec();
}

The final output of the program is
10
TestPropertyChanged 20

First print the value in the property " testProperty ", then to change the value in the property to 20, send a signal notification when the property changes, print " TestPropertyChanged 20 " in the handler function that receives the signal

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=325588427&siteId=291194637