Функция textFromValue преобразует целое число в строку. QSpinBox вызывает ее для обновления строки редактирования в наборном счетчике, когда пользователь нажимает клавиши верхней или нижней стрелки наборного счетчика. Мы используем статическую функцию QString::number, задавая 16 в качестве второго аргумента для преобразования значения в представленное в нижнем регистре шестнадцатеричное число, и вызываем функцию QString::toUpper для преобразования результата в верхний регистр.
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
04 #include
05 #include
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)