Главная · Все классы · Основные классы · Классы по группам · Модули · Функции

Система свойств Qt

Qt предоставляет сложную систему свойств, аналогичную поставляемой некоторыми поставщиками компиляторов. Тем не менее, как библиотека, не зависящая от компилятора и платформы, Qt не полагается на нестандартные возможности компилятора, такие как __property или [property]. Наше решение работает с любым стандартным компилятором C++ на всех поддерживаемых нами платформах. Оно основано на мета-объектной системе, которая также предоставляет межобъектную связь посредством сигналов и слотов.

Требования

Макрос Q_PROPERTY() в объявлении класса объявляет свойство. Свойства могут быть объявлены только в классах, унаследованных от QObject.

Для внешнего мира, свойство выглядит аналогично члену данных. Но свойства имеют несколько свойств, которые отличают их от обычных членов данных:

Функции чтения, записи и сброса могут быть почти функциями-членами, унаследованными или нет, виртуальными или нет. Единственным исключением является то, что функции-члены должны быть унаследованы от первого наследуемого класса в случае множественного наследования.

Чтение и запись свойств

Свойства можно читать и записывать посредством функций QObject не зная ничего об используемом классе. Во фрагменте кода ниже, вызов QObject::setProperty() эквивалентен вызову QAbstractButton::setDown():

 QPushButton *button = new QPushButton;
 QObject *object = button;
 // button and object point to the same object

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

Эквивалентны, т.е., за исключением того, что первый вариант быстрее и предоставляет более лучшую диагностику во время компиляции. На практике первый - наилучший. Тем не менее, поскольку вы можете получить список всех доступных свойств для любого QObject посредством его QMetaObject, QObject::setProperty() может дать вам контроль над классами, которые не доступны во время компиляции.

Так же как QObject::setProperty(), имеется соответствующая функция QObject::property(). QMetaObject::propertyCount() возвращает количество доступных свойств. QMetaObject::property() возвращает данные свойства для данного индекса свойства: объект QMetaProperty.

Простой пример

Вот простой пример, который показывает использование наиболее важных функций свойства:

 class MyClass : public QObject
 {
     Q_OBJECT

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

     enum Priority { High, Low, VeryHigh, VeryLow };
     void setPriority(Priority priority);
     Priority priority() const;
 };

Класс имеет свойство priority, которое ещё не известно мета-объектной системе. Для того, чтобы сделать свойство известным, вы должны объявить его с помощью макроса Q_PROPERTY(). Синтаксис следующий:

 Q_PROPERTY(type name
            READ getFunction
            [WRITE setFunction]
            [RESET resetFunction]
            [DESIGNABLE bool]
            [SCRIPTABLE bool]
            [STORED bool])

Для корректного объявления, функция получения значения должна быть константной и возвращать либо сам тип, либо указатель или ссылку на него. Необязательная функция записи значения должна возвращать void и получать ровно один аргумент, либо сам тип, либо указатель или ссылку на него. Это навязывает мета-объектный компилятор.

Тип свойства может быть любым поддерживаемым QVariant типом или типом перечисления, объявленным в самом классе. Так как MyClass использует для свойства Priority тип перечисления, этот тип должен быть также зарегистрирован с помощью системы свойств.

Можно установить значение по имени, например так:

 obj->setProperty("priority", "VeryHigh");

В случае свойств QList и QMap, переданное значение является QVariant, чьим значением является весь список или отображение.

Заголовочные файлы

Обычно необходимо для включения заголовочных файлов для каждого типа значения, которое вы используете в определениях свойства. Например:

 Q_PROPERTY(QDate date READ getDate WRITE setDate)

Так как свойство основано на классе QDate, заголовочный файл <QDate> будет включён в файл, содержащий вышеприведённое определение свойства.

Использование перечислений и флагов в свойствах

Типы перечислений регистрируются с помощью макроса Q_ENUMS(). Вот окончательное объявление класса, включающие объявления относящиеся к свойству:

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

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

     enum Priority { High, Low, VeryHigh, VeryLow };
     void setPriority(Priority priority);
     Priority priority() const;
 };

Обратите внимание на то, что если вы хотите зарегистрировать перечисление (используя Q_ENUMS()), которое объявлено в другом классе, перечисление должно быть полностью уточнённым с именем класса, объявившего его. Кроме того, класс объявивший перечисление унаследован от QObject, а также объявляет перечисление используя Q_ENUMS().

Другой аналогичный макрос - Q_FLAGS(). Аналогично Q_ENUMS(), он регистрирует тип перечисления, но отмечает в дополнение набор "флагов", т.е. значения перечисления могут соединены через ИЛИ. Класс ввода/вывода должен иметь значения перечисления Read и Write, а также принять Read | Write: например, перечисление лучше обрабатывается с помощью Q_FLAGS(), а не Q_ENUMS().

Типы свойств

Помимо ключевых слов READ и WRITE, каждое объявление Q_PROPERTY() может содержать дополнительные ключевые слова, которые поставляют информацию о свойстве:

Добавление дополнительной информации в класс

Прикреплённые к системе свойств дополнительным макросом, Q_CLASSINFO(), который может использоваться для присоединения дополнительных пар имя--значение к мета-объекту класса, например:

 Q_CLASSINFO("Version", "3.0.0")

Как и другие мета-данные, информация класса доступна во время выполнения через мета-объект; за подробностями обращайтесь к QMetaObject::classInfo().

Динамические свойства

В дополнение к свойствам, определённым используя Q_PROPERTY в классе возможно динамическое добавление и удаление свойств любого QObject во время выполнения.

Если вызывается setProperty со свойством не объявленном статически используя Q_PROPERTY, оно автоматически добавляется как динамическое свойство и его значение сохраняется в объекте. Значение может быть запрошено с использованием метода property(), также как со статическими свойствами.

Смотрите также Мета-объектная система и Сигналы и слоты.


Copyright © 2008 Trolltech Торговые марки
Qt 4.3.5