Библиотека сайта rus-linux.net
Разработка приложений с использованием Qt, часть 4
Оригинал: Developing Apps on Qt, Part 4Автор: Manoj Kumar
Дата публикации: 3 мая 2012 г.
Перевод: А.Панин
Дата публикации перевода: 8 ноября 2012 г.
В предыдущей статье мы поработали с механизмом сигналов и слотов, являющимся основой Qt при создании графических интерфейсов. В этой статье мы двинемся дальше и рассмотрим часть фреймворка Qt, предназначенную для создания графических интерфейсов.
Виджет является основным строительным блоком графического интерфейса любого приложения и позволяет выполнять такие функции, как создание кнопок, списков, и.т.д. В Qt класс QWidget является базовым классом для всех остальных классов компонентов графического интерфейса. В нем реализованы базовые функции, такие, как прием событий от клавиатуры и мыши.
Одним из самых простых, но очень важных виджетов является кнопка. Например, на Рисунке 1 показано диалоговое окно с двумя кнопками "Cancel" и "Close Tabs", которое отображается при попытке закрытия окна браузера Firefox с несколькими открытыми вкладками. Без кнопок графические интерфейсы становятся бесполезными. Все классы виджетов-кнопок наследуются от класса QAbstractButton, который представляет четыре сигнала - clicked(), pressed(), released() и toggled(), и пять состояний - isChecked(), isEnabled(), isDown(), setCheckable() и setAutoRepeat(). Мы затронем их в примере исходного кода позднее. Некоторые классы, наследуемые от QabstractButton: QPushButton, QRadioButton и QCheckBox.
Рисунок 1: Кнопки PushButton (или просто кнопки)
Давайте начнем рассмотрение виджетов с класса QPushButton. Этот виджет используется для того, чтобы позволить пользователю инициировать какое-либо действие, примерами являются кнопки "OK", "Отмена", "Применить", "Сохранить", и.т.д. Виджет QPushButton генерирует сигналы clicked(), pressed() и released(). Мы будем использовать механизм сигналов и слотов, описанный в предыдущей статье, для демонстрации принципа использования кнопок.
Создайте приложение с графическим интерфейсом ("GUI приложение Qt") и перетащите виджет pushButton на окно диалога. Вы можете изменить имя виджета со стандартного pushButton при помощи клика правой кнопкой мыши, выбора пункта "Изменить objectName" ("Change objectName") во всплывающем меню и ввода нового имени в появившемся окне. Таким же образом вы можете переименовать диалоговое окно и другие классы.
Примечание: исходный код программ из данной статьи доступен в формате zip-архива по ссылке. |
#ifndef DIALOG_H #define DIALOG_H #include <QDialog> namespace Ui { class Dialog; } class Dialog: public QDialog { Q_OBJECT public: explicit Dialog(QWidget *parent = 0); ~Dialog(); private: Ui::Dialog *ui; private slots: void button_clicked(); void button_pressed(); void button_released(); }; #endif // DIALOG_H
#include "dialog.h" #include "ui_dialog.h" #include <QtCore> Dialog::Dialog(QWidget *parent): QDialog(parent), ui(new Ui::Dialog) { ui->setupUi(this); connect(ui->clickme, SIGNAL(clicked()), this, SLOT(button_clicked())); connect(ui->clickme, SIGNAL(pressed()), this, SLOT(button_pressed())); connect(ui->clickme, SIGNAL(released()), this, SLOT(button_released())); } Dialog::~Dialog() { delete ui; } void Dialog::button_clicked() { qDebug() < "Button Clicked"; } void Dialog::button_pressed() { qDebug() < "Button Pressed"; } void Dialog::button_released() { qDebug() < "Button Released"; }
#include <QtGui/QApplication> #include "dialog.h" int main(int argc, char *argv[]) { QApplication a(argc, argv); Dialog w; w.show(); return a.exec(); }
В файле dialog.h мы объявили три частных функции-слота - button_clicked(), button_pressed() и button_released(). Их реализация в файле dialog.cpp просто выводит отладочные сообщения, указывая на то, что событие наступило. В конструкторе класса Dialog мы соединили эти слоты с сигналами clicked(), pressed() и released() объекта clickme(QPushbutton). Указатель "ui" ссылается на окно диалога; при помощи него мы можем осуществлять доступ к дочерним виджетам точно таким же образом, как мы получили доступ к объекту clickme в функциях connect().
Первым аргументом функции connect() (статической функции класса QObject) является объект-источник сигнала, вторым аргументом является сам сигнал, третьим аргументом является объект-приемник сигнала, а последним аргументом - функция-слот. Скомпилируйте вышеприведенный код и запустите программу. Когда появится диалоговое окно, нажмите кнопку clickme и проверьте наличие отладочных сообщений в консоли. Вывод показывает, что все три сигнала генерируются при нажатии на кнопку pushbutton: сначала сигнал pressed, затем released и наконец clicked.
Окна сообщений (Message-boxes)
Перед тем, как рассматривать другие классы, относящиеся к графическому интерфейсу, нам необходимо упомянуть важный класс QMessageBox, который очень часто используется. Например, при закрытии несохраненного документа в приложениях на Qt появляется всплывающее окно, использующее этот класс, с вопросом: хотите ли вы сохранить документ или закрыть без сохранения. Главным образом этот виджет используется для предупреждения пользователя; он может показывать текст и иконки, пользователю даже может быть предоставлена возможность ввести какой-либо текст.
int res = QMessageBox::information(this,"Option", "Want to choose " + item + "?",QMessageBox::Yes | QMessageBox::No ); switch(res) { case QMessageBox::Yes: ui->label_2->setText("You have chosen " + item); break; case QMessageBox::No: ui->label_2->setText("You haven't made any choice."); break; }
Окно сообщения с заданным "уровнем строгости" создано. Аргументами конструктора класса QMessageBox являются: указатель на родительский класс, заголовок окна, текст сообщения и маска, составленная из элементов энумератора, таких, как 'Yes", "No", "Save", и.т.д., с помощью которой задаются кнопки окна сообщения.
Когда окно отображено и пользователь нажимает одну из кнопок, оно исчезает, а функция возвращает один из элементов энумератора, указывающий на то, какая кнопка была нажата пользователем - это и позволяет вам решить, что делать дальше при помощи оператора case, как показано выше.
Радио-кнопки (Radio buttons)
void Dialog::on_radioButton_clicked(bool checked) { if(checked) item = ui->radioButton->text(); }
Вы можете выполнять действия в зависимости от значения переменной типа bool. Радио-кнопки используют "встроенный" виджет строки, поэтому вам не нужно использовать дополнительных виджетов для вывода текста рядом с кнопками.
Иногда необходимо выбрать сразу несколько вариантов из группы возможных - напрмер, пользователь выбирает три цвета из пяти. В этом случае радио-кнопки не подойдут и придется использовать виджет checkBox, который поддерживает два состояния и позволяет отмечать или не отмечать выбранные варианты. И снова сигнал clicked() генерируется при нажатии на кнопку, а переменная типа bool передается слоту. Код примера можно скачать по ссылке в примечании. Рисунки со 2 по 4 являются скриншотами получившегося приложения.
Рисунок 2: Кнопка выбора (CheckBox)
Рисунок 3: Радио-кнопки (RadioButtons)
Рисунок 4: Окно сообщения (MessageBox)
Помимо этих кнопок, в приложениях с графическим интерфейсом необходимы виджеты списков. Рассмотрим два виджета - раскрывающийся список (combo box) и список (list).
Раскрывающийся список предоставляет ниспадающее меню и показывает только выделенный элемент списка - в этом состоит достоинство виджета, поскольку он занимает минимум полезного пространства окна. В Qt этот виджет предоставляется классом QcomboBox. Элементы списка могут добавляться и удаляться также и во время исполнения программы. Сигнал генерируется в том случае, если пользователь меняет выбранный элемент. Если вы хотите предоставить пользователю возможность видеть сразу весь список, используйте класс QListWidget. Помотрите на Рисунок 5. Раскрывающийся список показывает только один элемент, а обычный список, представленный классом QListWidget - все элементы. Следующий код показывает, как добавлять элементы в эти списки...
ui->comboBox->addItem(ui->lineEdit->text());
QListWidgetItem * item = new QListWidgetItem( ui->lineEdit_2->text(), ui->listWidget); ui->listWidget->insertItem(ui->listWidget->count(), item);
Рисунок 5: Раскрывающийся список (ComboBox) и список (ListWidget)