![]() |
Главная · Все классы · Основные классы · Классы по группам · Модули · Функции | ![]() |
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 |