300.91K
Категория: ПрограммированиеПрограммирование

Разработка приложений с GUI

1.

Основы проектирования
программного обеспечения
Тема 3: Разработка приложений с GUI
ст. преп. каф. ВТ
Васильев В.С.

2.

Опрос
1. Какие есть варианты создания графического интерфейса в
различных языках программирования?
2. Какие проблемы решают фреймворки?
2

3.

int API.
WINAPI
WinMain
(
1.1 Windows
Hello
World
HINSTANCE hInst,
HINSTANCE hPrevInstance,
LPSTR cmdline,
int nCmdShow
) {/*…*/}
Создается сообщение и консоль
• hInst - дескриптор для данного экземпляра
программы;
• cmdline - командная строка;
• hPrevInstance – дескриптор предыдущего
экземпляра. В 16х позволял скопировать
данные предыдущего экземпляра этого же
приложения чтобы быстрее запуститься и
(при необходимости) взаимодействовать с
ним.
Из MSDN: “This parameter is always NULL. If you
need to detect whether another instance already
exists, create a uniquely named mutex using the
CreateMutex function”.
• nCmdShow - Определяет, как окно должно
быть показано: SW_HIDE, SW_MAXIMIZE,
SW_MINIMIZE,
SW_SHOWMAXIMIZED, SW_SHOWNA, …
3

4.

1.2 Windows API. Полезные типы данных.
Некоторые префиксы венгерской нотации
Префикс Значение
hDC
handle (указатель на контекст
устройства)
I
целое (integer)
L
длинный тип (long)
Lp
длинный указатель
Lpsz
указатель на строку,
заканчивающуюся нулевым
байтом
m_
переменная класса
N
short или int
P
указатель
Pfn
указатель на функцию
Pst
указатель на структуру
Psz
указатель на строку,
заканчивающуюся нулевым
байтом
Pv
указатель на тип void
S
строка
Sz
строка, заканчивающая нульсимволом
U
беззнаковый символ
Тип
Описание
HANDLE определяет идентификатор; 32-разрядное
целое, используемое в качестве дескриптора –
числа, определяющего некоторый ресурс
HWND
HDC
определяет идентификатор окна
определяет идентификатор контекста
устройства
LONG
LPSTR
NULL
UINT
32-битовое целое со знаком
Указатель (линейный)
0
Беззнаковый целый (32 бита для Win32)
WCHAR 16-битовый символ UNICODE. Используется
для представления символов языков мира
4

5.

1.2 Windows API. Обработка сообщений
GetMessage не отдает
управление программе, пока не
придет какое-либо сообщение.
DispatchMessage, определяет
предназначенное этому
сообщению окно и вызывает
соответствующую процедуру
обработки событий.
BOOL WINAPI GetMessag
e(
_Out_
LPMSG lpMsg,
_In_opt_ HWND hWnd,
_In_
n,
LRESULT DefWindowProc(
HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam
_In_
) ; // Передает обработку «ненужного сообщения» ОС
ax
);
UINT wMsgFilterMi
UINT wMsgFilterM
5

6.

1.2 Windows API. Более интересный
обработчик сообщений
6

7.

1.3 Windows API. Класс окна
Окно имеет: хэндл, заголовок, обработчик сообщений, стиль (сложная комбинация
флагов), цвет фона, вид курсора, …
7

8.

103
#define
1001
#define
1004
#define
1005
#define
1005
#define
1006
#define
1007
#define
1008
#define
1009
#define
1010
#define
1011
#define
1012
#define
1013
#define
1014
#define
1015
#define
1016
IDC_EDIT1
IDC_Continue
IDC_Break
1.4 Windows API. Ресурсы
// resources.rc:
IDC_N1
IDC_S1
IDC_C1
IDC_N2
IDC_S2
IDC_C2
IDC_N3
IDC_S3
IDC_C3
IDC_N4
IDC_S4
IDC_C4
8

9.

1.5 Windows API. Некоторые проблемы
и типичные ошибки
1. сложно структурировать код:
1.1 цикл обработки событий глобальный;
1.2 функция диспетчеризации вызовет
обработчик окна, но для этого все
обработчики надо зарегистрировать (в
одной точке?);
1.3 каждому ресурсу (строке, текстовому
полю, …) надо дать идентификатор,
причем, - уникальный в программе;
2. функции Win API имеют много
параметров;
3. многие параметры принимают int (в
качестве идентификатора) – проверка
типов отсутствует.
4. рисование внутри обработчика
WM_PAINT;
5. есть проекты типа MFC.
9

10.

2 Qt (в контексте разработки GUI)
1. ОО-Фреймворк;
2. локализует ресурсы;
3. реализует механизм передачи сообщения нужному
объекту;
4. «рисование» перенесено в виртуальную функцию;
5. предоставляет механизм сигналов и слотов (чем
сигналы отличаются от событий?);
6. предоставляет дополнительный механизм для
сборки мусора;
7. реализует стили по умолчанию, которые можно
менять при необходимости (нет лишних
параметров);
8. менять стили можно с использованием QSS;
9. предоставляет механизм свойств (Properties);
10.поддерживает механизм раскладок
(компоновщиков);
10
11.имеет среду разработки GUI мышкой;

11.

2.1 Qt. Сборка мусора
int main() {
Animal* a = new Animal();
Animal* b = new Animal(a);
Animal* c = new Animal(a);
delete a;
/*
A
/\
B C
*/
}
11

12.

2.1 Qt. Сборка мусора
class SuperBase {
SuperBase *m_parent;
public:
SuperBase(SuperBase* parent = nullptr) {
m_parent = parent_;
}
virtual ~SuperBase() {
//???
}
};
class Animal : public SuperBase {
public:
Animal(SuperBase* parent = nullptr) : SuperBase(parent) {
}
};
12

13.

2.1 Qt. Сборка мусора
class SuperBase {
SuperBase *m_parent;
vector<SuperBase*> m_children;
public:
SuperBase(SuperBase* parent = nullptr) {
m_parent = parent;
if (m_parent)
m_parent->add_child(this);
}
void add_child(SuperBase* child) {
m_children.push_back(child);
}
https://onlinegdb.com/rktK4EfYD
virtual ~SuperBase() {
for (auto* child : m_children) {
delete child;
}
cout << "~";
}
};
13

14.

2.1 Qt. Сборка мусора
struct Time : public SuperBase {
Time(SuperBase* parent = nullptr) : SuperBase(parent) {
}
};
struct Widget : public SuperBase {
Widget(SuperBase* parent = nullptr) : SuperBase(parent) {
}
};
struct ClockWidget : public Widget {
Time* m_time;
ClockWidget(SuperBase* parent = nullptr) : Widget(parent) {
m_time = new Time(this);
}
};
int main() {
ClockWidget clock;
}
https://onlinegdb.com/HJDRrEzKP
14

15.

2.2 Qt. Виджеты и события
class RunLine : public QLabel {
Q_OBJECT
public:
RunLine(QWidget *parent = 0);
public slots:
void setString(const QString string);
void setSpeed(const int speed);
protected:
virtual void timerEvent(QTimerEvent*);
int m_shift, m_timerId;
QString m_string;
};
https://pro-prof.com/archives/619
15

16.

2.2 Qt. Виджеты и события
void RunLine::timerEvent(QTimerEvent *) {
const int length = m_string.length();
if(++m_shift >= length)
m_shift = 0;
setText(m_string.right(m_shift) + m_string.left(length - m_shift));
}
void RunLine::setSpeed(const int speed) {
if (m_timerId)
killTimer(m_timerId);
m_timerId = 0;
if (speed < 0)
return;
if (speed)
m_timerId = startTimer(1000/speed);
}
void RunLine::setString(const QString string) {
m_string = string;
m_shift = 0;
setText(m_string);
}
https://pro-prof.com/archives/619
16

17.

2.3 Qt. Раскладки. Сигналы и слоты
MainWidget::MainWidget(QWidget *parent) : QWidget(parent) {
QGridLayout *layout(new QGridLayout(this));
QSpinBox *speedSpinbox(new QSpinBox(this));
QLineEdit *textLine(new QLineEdit(this));
RunLine *runline(new RunLine(this));
// ...
}
https://pro-prof.com/archives/619
17

18.

2.3 Qt. Раскладки. Сигналы и слоты
MainWidget::MainWidget(QWidget *parent) : QWidget(parent) {
QGridLayout *layout(new QGridLayout(this));
QSpinBox *speedSpinbox(new QSpinBox(this));
QLineEdit *textLine(new QLineEdit(this));
RunLine *runline(new RunLine(this));
layout->addWidget(textLine, 1, 1, 1, 1);
layout->addWidget(speedSpinbox, 1, 2, 1, 1);
layout->addWidget(runline, 2, 1, 1, 2);
}
https://pro-prof.com/archives/619
18

19.

2.3 Qt. Раскладки. Сигналы и слоты
MainWidget::MainWidget(QWidget *parent) : QWidget(parent) {
QGridLayout *layout(new QGridLayout(this));
QSpinBox *speedSpinbox(new QSpinBox(this));
QLineEdit *textLine(new QLineEdit(this));
RunLine *runline(new RunLine(this));
layout->addWidget(textLine, 1, 1, 1, 1);
layout->addWidget(speedSpinbox, 1, 2, 1, 1);
layout->addWidget(runline, 2, 1, 1, 2);
connect(speedSpinbox, SIGNAL(valueChanged(int)), runline, SLOT(setSpeed(int)));
connect(textLine, SIGNAL(textChanged(QString)), runline, SLOT(setString(QString)));
}
https://pro-prof.com/archives/619
19

20.

2.4 Qt. Использование QtDesigner
namespace Ui {
class MainUI;
}
class MainDialog :public QDialog {
Q_OBJECT
public:
explicit MainDialog(QWidget *parent = 0);
~MainDialog();
public slots:
private:
Ui::MainUI *m_ui;
};
https://pro-prof.com/archives/958
20

21.

2.4 Qt. Использование QtDesigner
https://pro-prof.com/archives/958
MainDialog::MainDialog(QWidget *parent)
: QDialog(parent), m_ui(new Ui::MainUI) {
m_ui->setupUi(this);
m_ui->m_counter->set(6, 200);
connect(m_ui->m_start, SIGNAL(clicked()), m_ui->m_counter, SLOT(on_start()));
connect(m_ui->m_stop, SIGNAL(clicked()), m_ui->m_counter, SLOT(on_stop()));
}
MainDialog::~MainDialog() {
delete m_ui;
}
21
English     Русский Правила