MyTetra Share
Делитесь знаниями!
О, смотри-ка какое хорошее место. Дайте два!
Зачем нужен макрос Q_PROPERTY и как им пользоваться
13.02.2018
21:31
Текстовые метки: qt, Q_PROPERTY, QML
Раздел: Компьютер - Программирование - Язык C++ - Библиотека Qt - Принципы написания кода

Макрос Q_PROPERTY необходим для того, чтобы программист имел возможность создавать класс со свойствами, поддерживаемыми метаобъектной подсистемой Qt.



Для чего может понадобиться метаобъектная подсистема Qt?


Например, если код пишется с использованием рефлексии, то у объекта можно узнавать перечень его свойств через QList<QByteArray> QObject::dynamicPropertyNames() const, или, например можно узнать имя класса в виде строки, вот так:


// Имея указатель на объект, узнать имя класса как строку

QObject *obj = new QPushButton;

obj->metaObject()->className(); // returns "QPushButton"


// Имея класс, узнать через специальный статический член имя класса как строку

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


Можно установить значение свойства по динамически изменяемому имени в виде строки, а не просто жестко прописывая в коде имя свойства. Делается это через метод:


bool QObject::setProperty(const char *name, const QVariant &value)


Точно так же, можно получать значение свойства по строке с именем свойства. Значение получается в виде QVariant:


QVariant QObject::property(const char *name) const


Кроме того, метаобъектная подсистема используется при программировании QML, для организации связки C++ и QML-кода. Связывать C++ и QML можно не только в режиме сигнал-слот, но и "пробрасывая" в QML объекты C++. Свойства класса, описанные в Q_PROPERTY, могут использоваться в QML-коде как обычные свойства QML-объектов.


Кроме того, свойства Q_PROPERTY поддерживаются средой разработки QtCreator, и визуально отображаются в структуре класса (представление "Обзор классов"), а так же в интерфейсе QtDesigner.



Что прописывается в макросе Q_PROPERTY?


В макросе Q_PROPERTY много настроечных директив, но обычно Q_PROPERTY используют примерно так:


class AppConfig : public QObject

{

Q_OBJECT

Q_PROPERTY(bool enabled READ isEnabled WRITE setEnabled)

...


Здесь имя свойства enabled - это именно то имя, под которым свойство будет видно в метаобъектной подсистеме для данного класса. Запись "bool enabled" не создает никакой C++ переменной для хранения значения свойства. Это просто объявление типа и имени свойства, которое будет доступно в метаобъектной подсистеме, и все.


Для того, чтобы считывать значение свойства, программист должен прописать прототип и реализацию публичного метода isEnabled , который в данном случае должен выглядеть вот так:


Файл заголовка (*.h - файл):


class AppConfig : public QObject

{

Q_OBJECT

Q_PROPERTY(bool enabled READ isEnabled WRITE setEnabled)


public:

bool isEnabled()

...


Файл реализации (*.cpp - файл)


bool AppConfig::isEnabled()

{

...

}


Qt не накладывает никаких ограничений на то, что должно происходить внутри метода isEnabled(). Qt не интересует, откуда будет браться возвращаемое методом значение. Значение можно хранить в каком-нибудь свойстве класса, можно читать с файла или из базы данных, оно может быть корректным или некорректным - это не важно, реализация остается за программистом.


Вызов isEnabled() производится в случае, если происходит считывание значения свойства enabled через метаобъектную систему. Так же, программист может просто вызывать данный метод чтобы получить значение этого свойства обычном способом в C++ коде.


То же самое можно сказать и про метод setEnabled(). Его реализация может выглядеть так:


void AppConfig::setEnabled(bool value)

{

...

}


Опять же, совсем не важно, куда будет записываться переданное в сеттер значение. Реализация этого метода лежит на совести программиста.



И все-таки, нужен пример реализации геттеров и сеттеров!


Хорошо, вот пример. Значение сохраняется в отдельное свойство класса, именуемое e:


Файл заголовка (*.h - файл):


class AppConfig : public QObject

{

Q_OBJECT


Q_PROPERTY(bool enabled READ isEnabled WRITE setEnabled)


public:

AppConfig(QObject *pobj=0);


bool isEnabled();

void setEnabled(bool value);


protected:

bool e;

};


Файл реализации (*.cpp - файл)


AppConfig::AppConfig(QObject *pobj)

{

Q_UNUSED(pobj);

}


bool AppConfig::isEnabled()

{

return e;

}


void AppConfig::setEnabled(bool value)

{

e=value;

}


Свойство для хранения значения могло бы быть определено под любым именем, и даже как bool enabled; - это не принципиально. Например, если выделить мышкой макрос Q_PROPERTY, вызвать контекстное меню и выбрать "Рефакторинг" - "Создание отсутствующих членов Q_PROPERTY, то будет сгенерирован код, в котором свойство для хранения значения будет называться m_enabled.


Вот, в принципе, и весь базис того, что необходимо знать о директиве Q_PROPERTY.


Так же в этом разделе:
 
MyTetra Share v.0.52
Яндекс индекс цитирования