В этой главе мы расскажем -- как создаются визуальные компоненты
(виджеты) в Qt. Визуальные компоненты могут создаваться путем
наследования существующих виджетов Qt или напрямую -- от QWidget. Мы продемонстрируем оба варианта, а так
же рассмотрим -- как можно интегрировать свои компоненты в
Qt
Designer. И в завершение главы представим компонент,
который использует прием двойной буферизации для устранения эффекта
мерцания во время перерисовки.
5.1.
Переделка существующих виджетов Qt.
Иногда возникает необходимость в расширении функциональных
возможностей стандартных виджетов. Самое простое решение -- это
создать класс потомок от соответствующего виджета Qt и наделить
его необходимыми свойствами.
В этом разделе мы продемонстрируем виджет шестнадцатиричного
счетчика. Стандартный виджет
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().