Глава 5. Создание собственных виджетов.

В этой главе мы расскажем -- как создаются визуальные компоненты (виджеты) в Qt. Визуальные компоненты могут создаваться путем наследования существующих виджетов Qt или напрямую -- от QWidget. Мы продемонстрируем оба варианта, а так же рассмотрим -- как можно интегрировать свои компоненты в Qt Designer. И в завершение главы представим компонент, который использует прием двойной буферизации для устранения эффекта мерцания во время перерисовки.

5.1. Переделка существующих виджетов Qt.

Иногда возникает необходимость в расширении функциональных возможностей стандартных виджетов. Самое простое решение -- это создать класс потомок от соответствующего виджета Qt и наделить его необходимыми свойствами.

Рисунок 5.1. Виджет HexSpinBox.


В этом разделе мы продемонстрируем виджет шестнадцатиричного счетчика. Стандартный виджет QSpinBox поддерживает только десятичный формат представления чисел, но, за счет создания дочернего класса, его можно "заставить" принимать и обрабатывать шестнадцатиричный формат. #ifndef HEXSPINBOX_H #define HEXSPINBOX_H #include <qspinbox.h> class HexSpinBox : public QSpinBox { public: HexSpinBox(QWidget *parent, const char *name = 0); protected: QString mapValueToText(int value); int mapTextToValue(bool *ok); }; #endif Большую часть своих функциональных возможнойстей, виджет HexSpinBox наследует от QSpinBox. Он имеет типичный конструктор и перекрывает две виртуальные функции своего предка. Поскольку класс HexSpinBox не определяет своих собственных сигналов и слотов, то он не нуждается в макроопределении Q_OBJECT. #include <qvalidator.h> #include "hexspinbox.h" HexSpinBox::HexSpinBox(QWidget *parent, const char *name) : QSpinBox(parent, name) { QRegExp regExp("[0-9A-Fa-f]+"); setValidator(new QRegExpValidator(regExp, this)); setRange(0, 255); } Пользователь может изменять значение счетчика либо щелкая по кнопкам со стрелками, либо вводя числа в окошко редактора. В последнем случае мы должны ограничить набор допустимых символов шестнадцатиричными цифрами. Для этого используется QRegExpValidator, который пропускает только символы из диапазонов (0..9), (A..F) и (a..f). Дополнительно задается диапазон изменения чисел -- от 0 по 255 (от 0x00 по 0xFF), который больше подходит для шестнадцатиричных чисел, чем диапазон (0..99), устанавливаемый QSpinBox по-умолчанию . QString HexSpinBox::mapValueToText(int value) { return QString::number(value, 16).upper(); } Функция mapValueToText() преобразует число в строку. Она используется для обновления окошка редактора, когда пользователь изменяет число нажатием на кнопки "вверх" и "вниз". Собственно преобразование выполняется функцией QString::number(), которой вторым аргументом передается число 16 -- основание системы счисления. Она возвращает шестнадцатиричное представление числа с символами в нижнем регистре, а вызов QString::upper() переводит их в верхний регистр. int HexSpinBox::mapTextToValue(bool *ok) { return text().toInt(ok, 16); } Функция mapTextToValue() выполняет обратное преобразование -- из строки в число. Она вызывается, когда пользователь вводит число с клавиатуры и завершает его нажатием на клавишу Enter. Собственно преобразование выполняется функцией QString::toInt(), которая принимает строку (возвращаемую вызовом QString::toInt()) и число 16 -- основание системы счисления.

Если преобразование было выполнено успешно, то QString::toInt() запишет в аргумент *ok значение true и false -- в противном случае. Это полностью соответствует тому, чего ожидает QSpinBox.

Это собственно все, что мы хотели рассказать о HexSpinBox. Расширение возможностей других виджетов Qt выполняется аналогичным образом: выбирается необходимый виджет, создается класс-потомок и перекрываются некоторые виртуальные функции, изменяющие поведение класса-предка. Это общепринятая в Qt техника программирования. Фактически мы с ней уже сталкивались в Главе 4, когда создавали класс-потомок от QTable и перекрывали методы createEditor() и endEdit().