17 int HexSpinBox::valueFromText(const QString &text) const
18 {
19 bool ok;
20 return text.toInt(&ok, 16);
21 }
Функция valueFromText() выполняет обратное преобразование из строки в целое число. Она вызывается в QSpinBox, когда пользователь вводит значение в строку редактирования наборного счетчика и нажимает клавишу Enter. Мы используем функцию QString::toInt() для попытки преобразования текущего текстового значения (возвращаемого QSpinBox::text()) в целое число, вновь используя 16 в качестве базы. Если строка не является правильным шестнадцатеричным числом, ok устанавливается на значение false и toInt() возвращает 0. Здесь нет необходимости рассматривать такую возможность, поскольку контролирующая функция (validator) позволяет вводить только правильные шестнадцатеричные значения. Вместо передачи адреса переменной ok мы могли бы задать нулевой указатель в первом аргументе функции toInt().
Этим мы завершили создание шестнадцатеричного наборного счетчика. Настройка других виджетов Qt осуществляется по тому же образцу: подобрать подходящий виджет Qt, создать его подкласс и переопределить несколько виртуальных функций для изменения режима его работы.
Создание подкласса QWidget
Многие пользовательские виджеты являются простой комбинацией существующих виджетов, либо встроенных в Qt, либо других пользовательских виджетов (таких, как HexSpinBox). Если пользовательские виджеты строятся на основе существующих виджетов, то они, как правило, могут разрабатываться в Qt Designer.
• создайте новую форму, используя шаблон «Widget» (виджет);
• добавьте в эту форму необходимые виджеты и затем расположите их соответствующим образом;
• установите соединения сигналов и слотов;
• если необходима функциональность, которую нельзя обеспечить с помощью механизма сигналов и слотов, необходимый программный код следует писать в рамках класса, который наследует как класс QWidget, так и класс, сгенерированный компилятором uic.
Естественно, комбинация существующих виджетов может быть также полностью запрограммирована вручную. При любом подходе полученный класс наследует непосредственно QWidget.
Если виджет не имеет своих собственных сигналов и слотов и не переопределяет никакую виртуальную функцию, можно просто собрать виджет из существующих виджетов, не создавая подкласс. Этим методом мы пользовались в главе 1 для создания приложения Age с применением QWidget, QSpinBox и QSlider. Даже в этом случае мы могли бы легко определить подкласс QWidget и в его конструкторе создать QSpinBox и QSlider.
Когда под рукой нет подходящих виджетов Qt и когда нельзя получить желаемый результат, комбинируя и адаптируя существующие виджеты, мы можем все же создать требуемый виджет. Это достигается путем создания подкласса QWidget и переопределением обработчиков некоторых событий, связанных с рисованием виджета и реагированием на щелчки мышки. При таком подходе мы свободно можем определять и управлять как внешним видом, так и режимом работы нашего виджета. Такие встроенные в Qt виджеты, как QLabel, QPushButton и QTableWidget, реализованы именно так. Если бы их не было в Qt, все же можно было бы создать их самостоятельно при помощи предусмотренных в классе QWidget открытых функций, обеспечивающих полную независимость от платформы.
Для демонстрации данного подхода при написании пользовательского виджета мы создадим виджет IconEditor, показанный на рис. 5.2. Виджет IconEditor может использоваться в программе редактирования пиктограмм.
Рис. 5.2. Виджет IconEditor.
Сначала рассмотрим заголовочный файл.
01 #ifndef ICONEDITOR_H
02 #define ICONEDITOR_H
03 #include <QColor>
04 #include <QImage>
05 #include <QWidget>
06 class IconEditor : public QWidget
07 {
08 Q_OBJECT
09 Q_PROPERTY(QColor penColor READ penColor WRITE setPenColor)
10 Q_PROPERTY(QImage iconImage READ iconImage WRITE setIconImage)
11 Q_PROPERTY(int zoomFactor READ zoomFactor WRITE setZoomFactor)
12 public:
13 IconEditor(QWidget *parent = 0);
14 void setPenColor(const QColor &newColor);
15 QColor penColor() const { return curColor; }
16 void setIconImage(const QImage &newImage);
17 QImage iconImage() const { return image; }
18 QSize sizeHint() const;
19 void setZoomFactor(int newZoom);