Наши партнеры

UnixForum





Библиотека сайта 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.

Кнопки PushButton (или просто кнопки)
Рисунок 1: Кнопки PushButton (или просто кнопки)

Давайте начнем рассмотрение виджетов с класса QPushButton. Этот виджет используется для того, чтобы позволить пользователю инициировать какое-либо действие, примерами являются кнопки "OK", "Отмена", "Применить", "Сохранить", и.т.д. Виджет QPushButton генерирует сигналы clicked(), pressed() и released(). Мы будем использовать механизм сигналов и слотов, описанный в предыдущей статье, для демонстрации принципа использования кнопок.

Создайте приложение с графическим интерфейсом ("GUI приложение Qt") и перетащите виджет pushButton на окно диалога. Вы можете изменить имя виджета со стандартного pushButton при помощи клика правой кнопкой мыши, выбора пункта "Изменить objectName" ("Change objectName") во всплывающем меню и ввода нового имени в появившемся окне. Таким же образом вы можете переименовать диалоговое окно и другие классы.

Примечание: исходный код программ из данной статьи доступен в формате zip-архива по ссылке.
Исходный код заголовочного файла примера использования класса QPushButton (dialog.h):
#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
Исходный код из файла dialog.cpp:
#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";
}
Исходный код из файла main.cpp:
#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 появляется всплывающее окно, использующее этот класс, с вопросом: хотите ли вы сохранить документ или закрыть без сохранения. Главным образом этот виджет используется для предупреждения пользователя; он может показывать текст и иконки, пользователю даже может быть предоставлена возможность ввести какой-либо текст.

Класс QMessgeBox также поддерживает установку "уровня строгости сообщения" ("message severity level"), в зависимости от которого устанавливается иконка рядом с текстом сообщения. Пример использования:
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)

Радио-кнопки предназначены для выбора одного варианта из группы возможных вариантов, причем в любой момент времени может быть выбран только один вариант. Во время выбора радио-кнопки, она генерирует сигнал clicked(). Пример функции-слота для обработки этого сигнала:
void Dialog::on_radioButton_clicked(bool checked)
{
	if(checked)
		item = ui->radioButton->text();
}

Вы можете выполнять действия в зависимости от значения переменной типа bool. Радио-кнопки используют "встроенный" виджет строки, поэтому вам не нужно использовать дополнительных виджетов для вывода текста рядом с кнопками.

Иногда необходимо выбрать сразу несколько вариантов из группы возможных - напрмер, пользователь выбирает три цвета из пяти. В этом случае радио-кнопки не подойдут и придется использовать виджет checkBox, который поддерживает два состояния и позволяет отмечать или не отмечать выбранные варианты. И снова сигнал clicked() генерируется при нажатии на кнопку, а переменная типа bool передается слоту. Код примера можно скачать по ссылке в примечании. Рисунки со 2 по 4 являются скриншотами получившегося приложения.

Кнопка выбора (CheckBox)
Рисунок 2: Кнопка выбора (CheckBox)

Радио-кнопки (RadioButtons)
Рисунок 3: Радио-кнопки (RadioButtons)

Окно сообщения (MessageBox)
Рисунок 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);

Раскрывающийся список (ComboBox) и список (ListWidget)
Рисунок 5: Раскрывающийся список (ComboBox) и список (ListWidget)