Upload
juno-nguyen
View
72
Download
0
Embed Size (px)
DESCRIPTION
tai lieu QT
Citation preview
Основы графического интерфейса пользователя
● Понятие графического интерфейса пользователя, окна и виджета
● Категории виджетов● Создание макета окна в редакторе форм
(QT-Designer). Задание свойств виджетов● Проблема различных разрешений экрана.
Управление размещением виджетов
1
Основы графического интерфейса пользователя
● Объекты, соответствующие виджетам, доступ к ним из программы
● Понятие программы, управляемой событиями
● Понятие сигналов и слотов● Использование сигналов и слотов для
реализации программы, управляемой событиями
2
Раздел I. Понятие графического интерфейса пользователя
● Графический интерфейс пользователя (GUI) — это интерфейс, основанный на представ-лении всех доступных пользователю функ-ций в виде графических компонентов экрана (окон, значков, меню, кнопок, списков и т.п.).
● GUI-программа обычно представляет собой множество окон, каждое из которых содержит множество элементов управления.3
Основные понятия
● Окно представляет собой «отдельный» экран отображающий различную инфор-мацию и реагирующий на действия поль-зователя, в частности может содержать набор элементов управления (виджетов).
● Виджет (Widget = Window - окно + Gadget - приспособление) - это элемент управления, способный реагировать на действия пользо-вателя.
4
Категории виджетов
● Виджеты отображения● Виджеты ввода данных● Виджеты выбора● Кнопки● Виджеты группировки
Далее рассматриваются виджеты из библиотеки QT Library
5
Виджеты отображения
● Виджеты отображения не принимают актив-ного участия в действиях пользователя, они используются только для информирования его о происходящем.
6
Виджеты отображения
● Метка (Label) – текстовое поле, текст в котором не подлежит изменению со стороны пользователя, в QT Library также используется для отображения графического изображения
● Индикатор прогресса (ProgressBar) – показывает процесс выполнения опе-рации и заполняется, по мере ее вы-полнения, справа-налево
● Электронный индикатор (LCDNumber) используется для отображения целых чисел7
Виджеты ввода данных
● Данная группа виджетов представляет собой основу пользовательского ввода и редакти-рования данных.
● Большая часть элементов ввода может ра-ботать с буфером обмена
● Текст можно выделять с помощью мыши, клавиатуры и контекстного (выпадающего по правой кнопке «мышки») меню
8
Виджеты ввода данных
● Однострочное поле ввода (LineEdit) — использу-ется для ввода строки за-данной длины. Возможно задать шаблон ввода (маску), а также проверку вводимой информации (валидатор)
● Редактор многострочного текста (TextEdit)
9
Виджеты ввода данных
● Счетчики (SpinBox и DoubleSpinBox) – ис-пользуются для ввода целых и дробных чисел из определенного диапа-зона.
● Элементы ввода даты и времени(DateEdit, TimeEdit и DateTimeEdit).
10
Виджеты выбора
● Виджеты выбора используются для выбора пользователем одного или нескольких зна-чений из заданного множества.
11
Виджеты выбора
● Простой список (ListWidget) – поддерживает одноэлементный и множественный выбор.
● Выпадающий список (ComboBox).
● Таблица (TableWidget) – в отличие от простого списка имеет несколько информационных колонок.
● Дерево (TreeWidget) - позволяет отображать список в иерархической форме (например, содержимое дис-ков и каталогов).12
Кнопки● Командная кнопка (PushButton -
кнопка нажатия) – активизирует вы-полнение некоторого действия. Раз-личают обычную кнопку, кнопку-вы-ключатель и кнопку-меню.
● Флажок (CheckBox)– используется для задания логических значений. Может иметь третье, неопределен-ное, состояние.
● Переключатель (RadioButton)– обеспечивает выбор только одной опции из нескольких (см. виджеты выбора).13
Применение виджетов для отобра-жения и редактирования данных
14
Тип данных Виджетцелое число SpinBoxвещественное число DoubleSpinBoxстрока LineEditтекст TextEditдата DateEditвремя TimeEditдата и время DateTimeEditфлаг CheckBoxэлемент из перечня ComboBox, ListWidget,
группа RadioButtonмножество элементов из перечня
ListWidget, группа CheckBox
Организация выбора
● Если производится выбор из 2-5 вариантов, причем количество вариантов не зависит от действий пользователя, то для выбора удоб-нее применить набор переключателей.
● Если количество вариантов зависит от дей-ствий пользователя, то
– при небольшом количестве вариантов (2-8) ис-пользуется выпадающий список;
– при большом количестве вариантов (более 8) ис-пользуется простой список.15
Задание
● Каким бы способом вы организовали выбор в следующих случаях:
a) выбор пола человека при хранении данных меди-цинского обследования;
b) выбор станции назначения при покупке железно-дорожного билета;
c) выбор варианта оплаты товара (наличными, кре-дитной карточкой, webmoney и т.д.)
16
Организация выбора
a) выбор пола человека — варианты неизменны, ко-личество 2 — использовать набор переключа-телей;
b) выбор станции назначения — возможно добавле-ние новых станций, количество станций высоко — использовать простой список;
c) выбор варианта оплаты товара — возможно по-явление новых способов оплаты, количество не-велико — использовать выпадающий список.
17
Виджеты группировки
● Данная категория виджетов используется для объединения виджетов в смысловые группы.
● Использование виджетов группировки иногда изменяет поведение виджетов, входящих в группу (например, переключателей).
● Над виджетами, входящих в группу, можно выполнять операции как с одним целым (например, активировать, скрывать и т.д.).
18
Виджеты группировки● Виджет «группа» (GroupBox)
объединяет несколько виджетов под одним заголовком.
● Виджет «закладки» (TabWidget) включает в себя несколько групп ви-джетов, отображающихся в одном месте. Пользователь выбирает за-кладками, какую группу смотреть.
● Виджет «стопка» (StackedWidget) похож на закладки, но закладки не видны, выбор показываемой группы виджетов осуществляет программа. 19
Виджеты группировки
● Виджет «группа» может иметь кнопку типа «флажок», прикрепленную к его имени. В этом случае флаг автоматически управляет активностью виджетов группы.
20
Виджеты группировки
● Виджет «закладки» используется когда все необходимые виджеты не помещаются на окно.
● Виджет «стопка» используется если при различных условиях в одной и той же части окна необходимо показать разные наборы виджетов.
21
Разработка однооконной программы
1) Создайте проект QT Application2) Создайте макет окна3) Объявите в классе окна дополнительные
свойства для хранения данных (состояния) программы
4) Создайте и закодируйте слоты5) Свяжите слоты с сигналами, напишите код
инициализации программы22
Раздел II. Создание проекта и макета окна
1) Создайте проект QT Application2) Задайте в качестве главного окна програм-
мы класс QMainWindow3) Расставьте виджеты на макете окна, пере-
таскивая их из панели инструментов на форму
4) Задайте основные свойства виджетов
23
Создание проекта QT Application
24
Задание в качестве главного окна программы QMainWindow
25
Выбор макета окна в проекте
26
Расстановка виджетов на макете окна
27
Расстановка виджетов на макете окна, задание их основных свойств
28
Понятие фокуса
● Пользователь в каждый момент времени может работать только с одним виджетом - виджетом, который имеет фокус.
● Если виджет в фокусе, то данные с клавиатуры направляются этому виджету.
● Перенаправить фокус с одного виджета на другой можно с помощью мыши или клавиш Tab (прямой обход) и Shift+Tab (обратный обход).
29
Проблема различных разрешений экрана
● Разрешение экрана, в котором создается макет окна, может отличаться от рабочего разрешение экрана
● Если разрешение меньше, то видны не все виджеты
● Если разрешение больше, то большая часть экрана не используется
30
Решение проблемы различных разрешений экрана
● Необходимо растягивать/сжимать виджеты и пространство между ними в соответствии с текущим разрешением экрана.
● Различные виджеты должны сжиматься и растягиваться по-разному с учетом их текущего содержимого.
● В QT Library проблема различных разре-шений экрана решается с помощью лэйаутов (layout).
31
Лэйауты
● Горизонтальный (HBoxLayout)
● Вертикальный (VBoxLayout)
● Табличный (GridLayout)
● «Пружина» или «пробел» (SpacerItem)
32
Пример использования лэйаутов
33
Пример «растягивающегося» окна:«растягиваются» поля ввода, таблица и пространство
между кнопками «Close» и «Help»
Пример использования лэйаутов
Горизонтальный лэйаут
Табличный лэйаутВертик. лэйаут
34
Пружина
Раздел III. Программная модель GUI. Класс главного окна
● При создании макета окна в программе ав-томатически создается класс главного окна, производный от класса QMainWindow.
● Класс главного окна содержит в себе:– объекты, соответствующие виджетам, ко-
торые расположены на макете окна;– данные, время жизни которых совпадает
со временем жизни программы;– функции, которые выполняет программа в
ответ на действия пользователя.35
Пример класса главного окнаclass PrimitiveCalc : public QMainWindow{ Q_OBJECTpublic:
// Конструктор и деструктор PrimitiveCalc(QWidget *parent=0,Qt::WFlags flags=0); ~PrimitiveCalc();private:
// Виджеты, расположенные на макете окна Ui::PrimitiveCalcClass ui;
// Данные......
private slots:// Слоты, т.е. функции, реагирующие на// действия пользователя......
};36
Объекты, соответствующие виджетам
● Каждому виджету, расположенному на макете окна, в классе главного окна автоматически со-здается объект. Эти объекты хранятся как поля свойства класса главного окна с именем ui
● Доступ к такому объекту внутри класса главно-го окна осуществляется с помощью выраже-ния:
ui.<имя объекта>где <имя объекта> задается при построении макета окна37
Задание виджету имени объекта
38
Калькулятор содержит3 виджета типа SpinBox:●LValueBox●RValueBox●ResultBox
Задание виджету имени объекта
39
Калькулятор содержит 3 виджета типа SpinBox:●LValueBox●RValueBox●ResultBox
: PrimitiveCalc
ui : UI::PrimitiveCalcClassУказатели:LValueBoxRValueBoxResultBox
: QDoubleSpinBox
Объекты для виджетов:
Методы, работающие с виджетамиИмена классовИмена полей классов
Доступ к виджетам из программы● Выражение ui.<имя объекта> возвращает
указатель на объект, соответствующий ви-джету
● Пример: – пусть для одного из счетчиков, располо-
женных на макете окна, определено имя LValueBox
– счетчик описывается классом QDoubleSpinBox
– тогда выражение ui.LValueBox будет иметь тип QDoubleSpinBox *40
Задание● Диалог калькулятора содержит виджет LValueBox
типа QDoubleSpinBox.● Класс QDoubleSpinBox содержит следующие (ди-
намические) методы:– double value() - возвращает значение, введен-
ное в виджете;– void setValue(double value) — устанавлива-
ет в виджет новое значение.● Напишите фрагмент кода, которая прибавит к значе-
нию виджета LValueBox единицу. Считать, что фрагмент кода расположен в функции, принадле-жащей классу главного окна.41
Доступ к виджетам из программы
// Инкремент значения виджетаdouble value;// Считываем значение виджетаvalue = ui.LValueBox->value();// Устанавливаем значение виджетаui.LValueBox->setValue(value + 1);
// Или в одной строке:ui.LValueBox->setValue(ui.LValueBox->value() + 1);
42
Задание● Диалог калькулятора содержит виджеты LValueBox
и RValueBox типа QDoubleSpinBox, вводящие два слагаемых, а также виджет ResultBox для отобра-жения результата.
● Класс QDoubleSpinBox содержит следующие (ди-намические) методы:
– double value() - возвращает значение, введен-ное в виджете;
– void setValue(double value) — устанавливает в виджет новое значение.
● Напишите функцию add класса главного окна PrimitiveCalc, которая отобразит в ResultBox сумму значений LValueBox и RValueBox.43
Доступ к виджетам из программы
// Сложение двух чиселvoid PrimitiveCalc::add(){
double LValue, RValue; // операнды
// Считываем операнды из двух счетчиковLValue = ui.LValueBox->value();RValue = ui.RValueBox->value();// Вычисляем результат и отображаем его // в третьем счетчикеui.ResultBox->setValue(LValue + RValue);
}
44
Классы, соответствующие виджетам
● Каждому виджету соответствует определен-ный класс со своим набором свойств и мето-дов.
● В QT Library имя класса виджета задается по следующему принципу: к английскому на-званию виджета добавляется большая буква Q, например, QDoubleSpinBox.
● Для использования класса необходимо под-ключить заголовочный файл, соответствую-щий имени класса, например,
#include <QDoubleSpinBox>45
Пример описания класса QDoubleSpinBox
Properties — основные свойстваmaximum : double singleStep : doubleminimum : double value : double Public Functions — методы чтения/записи свойствQSpinBox ( QWidget * parent = 0 ) QString cleanText () const void setRange ( double minimum, double maximum ) void setSingleStep ( double val ) double singleStep () const double value () const Public Slots — особый метод- слотvoid setValue ( double val )
46
GUI-программа — это реактивная программа
● Последовательность действий в активной программе полностью определяется ее ко-дом (набором процедур).
● Последовательность действий в реактивной программ определяется пользователем, т.к. программа выполняет процедуры, реагируя на воздействия пользователя.
● Реактивная программа представляет собой набор независимых процедур, взаимодей-ствующих между собой посредством общих данных формирующих состояние программы.47
Понятие сигнала
● Когда пользователь воздействует на виджет, то виджет изменяет свое состояние и испус-кает сигнал, извещая программу об этом со-бытии.
● Каждый вид виджет обладает своим предопределенным набором сигналов. Например, нажатие на командную кнопку (QPushButton) приводит к испусканию сиг-нала toggled.
48
Понятие слота
● Если программе требуется отреагировать на некоторое событие, то в ней должен быть со-здан обработчик события, также называемый слотом (от англ. slot - разъем).
● Слот — это функция, имеющая тип void, ко-торая может вызываться в ответ на испуска-ние сигнала.
● Для того чтобы слот был вызван в ответ на сигнал, он должен быть соединен с сигналом. Обычно это выполняется в конструкторе окна.49
Соединение слотов и сигналов
● Для соединения сигналов и слотов использу-ется метод connect, доступный в любом классе библиотеки Qt:
bool connect(<указатель на источник сигнала>, SIGNAL(<прототип сигнала>), <указатель на получатель сигнала>,
SLOT(<прототип слота>));● Метод connect возвращает успешность
соединения (обычно используется при отладке).50
Соединение слотов и сигналов● <указатель на источник сигнала> - это
указатель на объект виджета, испускающего сигнал
● <указатель на получатель сигнала> - обычно это указатель на окно, к которому при-надлежит виджет. При этом обычно использу-ется ключевое слово this, содержащее указа-тель на текущий объект.
● в прототипах сигнала и слота указывают-ся типы всех аргументов, но НЕ указываются тип возвращаемого значения и имена аргумен-тов51
Задание
У виджета «таблица» (QTableWidget) имеется сигнал, который испускается, когда фокус
переходит от одной ячейки таблицы к другойvoid currentCellChanged (
int currentRow, int currentColumn, int previousRow, int previousColumn )
где previousRow и previousColumn — индексы той ячейки, которая имела фокусcurrentRow, currentColumn - индексы той ячейки, которая получила фокус52
Задание
Соедините сигнал об изменении текущей клетки таблицы mainTable со слотом класса
MyWindowvoid selection_changed(int currentRow, int currentColumn, int previousRow);
Соединение выполните в конструкторе класса MyWindow
53
Пример соединения слота
// Конструктор класса окна MyWindow::MyWindow()...{ ....
connect(ui.mainTable, SIGNAL(currentCellChanged(int, int, int, int)), this, SLOT(selection_changed(int, int, int)));
}
54
Свойства сигналов и слотов
● Сообщения, посылаемые посредством сиг-налов, могут иметь множество аргументов любого типа.
● Сигнал можно соединять с любым количе-ством слотов. Сигнал поступит ко всем под-соединенным слотам (в произвольном по-рядке).
● Слот может принимать сообщения от многих сигналов, принадлежащих разным объектам.
55
Объявление слотов
● Слот обычно объявляется как закрытый ме-тод класса окна в специальном разделе slots.
● Слот не возвращает значения.
● Слот может иметь аргументы, если они определены в сигнале, при этом их тип и по-рядок должны совпадать.
● Слот может использовать только часть (на-чальную) аргументов сигнала.
56
Пример объявления слотов
● В программе «Калькулятор» все действия выполняются по нажатию пяти кнопок, соот-ветственно должно быть создано пять раз-личных обработчиков событий (слотов).
● У кнопки имеется сигнал clicked, который испускается, когда кнопка нажимается мы-шью, а затем отпускается:void clicked (bool checked = false)
● Так как используется не флажок, то аргумент сигнала не используется.
57
Пример объявления слотов
// Объявление класса class PrimitiveCalc : public QMainWindow...{ ...private slots: //СЛОТЫ:
void on_addition(); // Сложение двух чиселvoid on_subtraction();// Вычитание двух чиселvoid on_product(); // Произвед. двух чиселvoid on_division(); // Деление двух чиселvoid on_recovery(); // Помещение результата
// в операнд};58
Схема соединения слотов и сигналов
59
Таблица соединения слотов и сигналов
Сигнал Слот
on_subtraction()on_product()on_division()
Источник сигнала
Приемник сигнала
btnAddition clicked() this on_addition()btnSubtractionclicked() thisbtnProduct clicked() thisbtnDivision clicked() this
btnRecovery clicked() this on_recovery()
60
Пример соединения слотов и сигналов
// Конструктор класса окнаPrimitiveCalc::PrimitiveCalc(QWidget *parent,
Qt::WFlags flags) : QMainWindow(parent, flags){
// Команда необходима для автоматичсекого// создания объектов, соотвествующих виджетамui.setupUi(this);
// Связываем слоты с сигналамиconnect(ui.btnAddition,SIGNAL(clicked()),this,
SLOT(on_addition())); connect(ui.btnSubtraction,SIGNAL(clicked()),
this, SLOT(on_subtraction())); .....}61
Задание
У виджета «таблица» (QTableWidget) имеется сигнал, который испускается, когда фокус
переходит от одной ячейки таблицы к другойvoid currentCellChanged (
int currentRow, int currentColumn, int previousRow, int previousColumn )
где previousRow и previousColumn — индексы той ячейки, которая имела фокусcurrentRow, currentColumn - индексы той ячейки, которая получила фокус62
Задание
Создайте в классе окна MyWindow слот selection_changed(), который бы выставлял флажок “Вниз”, если фокус перешел к ячейке,
расположенной ниже текущей, и сбрасывал его в потивном случае.
Таблица называется table.Флажок “Вниз” называется checkDown.
Для выставления/сброса флажка воспользуйтесь методом
void setChecked ( bool )63
Пример объявления слота
// Объявление класса class MyWindow : public QMainWindow{ ...private slots: //СЛОТ
void selection_changed(int currentRow, int currentColumn, int previousRow);
};
64
Пример соединения слота
// Конструктор класса окна MyWindow::MyWindow()...{ ....
connect(ui.table, SIGNAL(currentCellChanged(int, int, int, int)), this, SLOT(selection_changed(int, int, int)));
}
65
Пример реализации слота
// Слот void MyWindow::selection_changed(int currentRow,
int currentColumn, int previousRow){
bool isDown; // выбрана ячейка справа
isDown = currentRow > previousRow;
ui.checkDown->setChecked(isRight);}
66
Объявление и испускание сигнала
● Возможно создание собственного сигнала.
● Сигнал обычно объявляется как открытый метод класса окна в специальном разделе signals.
67
Объявление и испускание сигнала
● Сигнал не возвращает значения (возвраща-емое значение типа void).
● Сигнал может иметь аргументы.
● Сигнал не имеет тела (кода).
● Испускание сигнала аналогично вызову функции, но предваряется ключевым словом emit
68
Объявление и испускание сигнала
// Описание классаclass MyWindow : public QMainWindow{...public signals:
// Сигнал, который испускается при создании окна.// Параметр показывает успешное выделение памяти void create(bool);
private:int *mass; // динамический массив целых чиселint count; // длина массива
};69
Объявление и испускание сигнала
// Конструктор класса окнаMyWindow::MyWindow(QWidget *parent,Qt::WFlags flags) : QMainWindow(parent, flags){
// Выделяем памятьmass = (int *)malloc(1000*sizeof(int));count = 1000;
// Вызов сигналаemit create(mass != NULL);
}
70
Это надо помнить!
● Класс окна содержит следующие свойства:
– объект ui, содержащий указатели на объекты виджетов окна — создается автоматически;
– данные, которые необходимо хранить все время работы программы — задаются про-граммистом.
● Класс окна содержит следующие методы:
– слоты, выполняющие определенную работу в ответ на действия пользователя.71
Это надо помнить!
● При создании слотов:– остерегайтесь начинать имя слота с on_, т.к.
слоты, чьи названия соответствуют шабло-ну on_<имя объекта>_<имя сигнала> подсоединяются автоматически и вы можете получить двойное соединение;
– вы не обязаны получать все параметры сиг-нала, можете использовать только часть (первых) или не использовать их вообще;
72
Это надо помнить!● При соединении слотов:– строго соблюдайте правила записи прототипов сиг-
нала и слота — указывать типы аргументов, но не указывать тип возвращаемого значения и имена аргументов;
– проверить, вызывается ли слот можно, поставив в начале его точку останова и произведя действие, испускающее нужный сигнал — точка останова сработает если был вызван слот;
– если слот не вызывается, проверьте, возвращает ли функция connect значение true, если нет то ошибка связана с написанием вызова connect73
Это надо помнить!
● При написании кода слотов:– все изменения данных, которые делает слот,
должны быть произведены в двух местах● в полях класса главного окна, хранящих
глобальную информацию;● в виджетах на экране.
74
Это надо помнить!● При написании кода слотов:– некоторые сигналы испускаются не только в
ответ на действия пользователя, но и про-граммы, например сигнал об изменении те-кущей клетки таблицы currentCellChanged в таблице испускается в двух случаях:● когда пользователь выбрал новую клетку
таблицы;● когда программа изменила текущую клетку
(например вызовом функции setCurrentRow).75