46
Темы лекции: Введение в Qt. Программирование GUI. Практическое задание: GUI приложение на Qt. Тренер: Игорь Шкулипа, к.т.н. С++ Библиотеки STL и Qt. Занятие 3

C++ STL & Qt. Занятие 03

Embed Size (px)

Citation preview

Page 1: C++ STL & Qt. Занятие 03

Темы лекции: Введение в Qt. Программирование GUI.

Практическое задание: GUI приложение на Qt.

Тренер: Игорь Шкулипа, к.т.н.

С++ Библиотеки STL и Qt. Занятие 3

Page 2: C++ STL & Qt. Занятие 03

http://www.slideshare.net/IgorShkulipa 2

Библиотека Qt

Библиотека QT предназначена для разработки GUI, разработаннаякомпанией Trolltech AS. Qt была представлена в 1996 году.

Qt является кроссплатформенной, есть реализации библиотеки дляMS/Windows, Unix/X11, Macintosh и Embedded платформ.

Библиотека является объектно-ориентированной, базирующейся накомпонентах и имеет богатое разнообразие различных визуальныхэлементов - виджетов (widgets), предоставляемых в распоряжениепрограммиста.

Библиотека включает в себя :

• Среду для разработки графического интерфейса.• Компилятор мета-объектов.• Набор классов для работы.

Page 3: C++ STL & Qt. Занятие 03

http://www.slideshare.net/IgorShkulipa 3

Типы в Qt

Для переносимости кода

qint8 8-битное знаковое целое

quint8 8-битное беззнаковое целое

qint16 16-битное знаковое целое

quint16 16-битное беззнаковое целое

qint32 32-битное знаковое целое

quint32 32-битное беззнаковое целое

qint64 64-битное знаковое целое

quint64 64-битное беззнаковое целое

quintptr Беззнаковый указатель (32 или 64 бита)

qptrdiff Знаковый указатель (32 или 64 бита)

qreal Везде double; float только для архитектуры ARM

Для краткой записи типовuchar unsigned charuint unsigned intulong unsigned longushort unsigned short

qlonglong long long int или __int64

qulonglong unsigned long long int или unsigned __int64

Page 4: C++ STL & Qt. Занятие 03

http://www.slideshare.net/IgorShkulipa 4

Регистрация типов

Для эффективной работы с данными (в частности, в контейнерах)определенному коду требуется информация о типах. В Qt ее можноуказать при помощи Q_DECLARE_TYPEINFO:

Q_DECLARE_TYPEINFO (Type, Flags)

где Type – тип, Flags – флаг:

• Q_PRIMITIVE_TYPE – примитив без конструктора и деструктора;• Q_MOVABLE_TYPE – тип с конструктором и/или деструктором,

который можно перемещать в памяти при помощи memcpy();• Q_COMPLEX_TYPE – сложный тип с конструктором и/или

деструктором, который нельзя перемещать в памяти.

Page 5: C++ STL & Qt. Занятие 03

http://www.slideshare.net/IgorShkulipa 5

Обзор классов библиотеки

Page 6: C++ STL & Qt. Занятие 03

http://www.slideshare.net/IgorShkulipa 6

Объектная модель

Для эффективной работы с классами на стадии выполнения в Qtиспользуется специальная объектная модель, расширяющая модельC++. В частности, добавляются следующие возможности:

• древовидные иерархии объектов;• аналог dynamic_cast для библиотеки, не использующий RTTI;• взаимодействие объектов через сигналы и слоты;• свойства объектов.

Многие объекты определяются значением сразу нескольких свойств,внутренними состояниями и связями с другими объектами. Онипредставляют собой индивидуальные сущности, и для них не имеетсмысла операция копирования, а также разделение данных в памяти.В Qt эти объекты наследуют свойства QObject.

Инструментарий спроектирован так, что для QObject и всех его потомковконструктор копирования и оператор присваивания недоступны – ониобъявлены в разделе private через макрос Q_DISABLE_COPY():

class SomeClass : public QObject

{

private:

Q_DISABLE_COPY(SomeClass)

};

Page 7: C++ STL & Qt. Занятие 03

http://www.slideshare.net/IgorShkulipa 7

Объектная модель

Таким образом, не стоит использовать конструкцию:SomeClass c1 = SomeClass (c);

вместо:SomeClass c1 (c);

Другие объекты (например, контейнеры и строки) полностьюопределяются представляемыми данными, поэтому в соответствующихклассах имеются операция присваивания и конструктор копирования.Кроме того, объекты, представляющие одинаковые данные, могутпрозрачно для программиста разделять их в памяти.

Page 8: C++ STL & Qt. Занятие 03

http://www.slideshare.net/IgorShkulipa 8

Метаобъекты

Часть расширений реализована стандартными методами C++, однако Qtиспользует и более сложные синтаксические расширения, поэтому ониспользует автоматическую генерацию кода.

Для этого в C++ реализован механизм шаблонов, но он не предоставляетвсех необходимых Qt возможностей, плохо совместим с динамическойобъектной моделью и в полной мере не поддерживается всемиверсиями компиляторов.

В сложных ситуациях Qt использует свой компилятор метаобъектов(moc), преобразующий код с расширениями в стандартный код C++.Для обозначения того, что класс использует метаобъектныевозможности (и, соответственно, должен обрабатываться moc), вразделе private нужно указать макрос Q_OBJECT.

Во избежание ошибок Q_OBJECT лучше использовать во всех классах,наследуемых от QObject (косвенно либо напрямую).

class SomeClass: public QObject {

Q_OBJECT

public:

SomeClass();

}

Page 9: C++ STL & Qt. Занятие 03

http://www.slideshare.net/IgorShkulipa 9

qobject_cast

Для динамического приведения QObject используется функция

T qobject_cast (QObject *object);

Она работает как стандартная операция dynamic_cast в C++, но нетребует поддержки со стороны системы динамической идентификациитипов (RTTI).

Page 10: C++ STL & Qt. Занятие 03

http://www.slideshare.net/IgorShkulipa 10

Свойства

Свойство – составляющая часть объекта, доступ к которойосуществляется как к члену объекта, но таковым не является(реализуют принцип инкапсуляции для членов объекта).

В некоторых объектно-ориентированных языкахпрограммирования (например, в C++) свойства, как элементязыка, отсутствуют.

В этом случае в класс добавляют методы, посредством которыхосуществляется доступ к необходимым переменным класса.

В Qt свойства реализованы с помощью макроса Q_PROPERTY().

Page 11: C++ STL & Qt. Занятие 03

http://www.slideshare.net/IgorShkulipa 11

Свойства

Чтобы объявить свойство, необходимо использовать макросQ_PROPERTY() в классе, который унаследован от QObject.

Q_PROPERTY(type name

READ getFunction

[WRITE setFunction]

[RESET resetFunction]

[NOTIFY notifySignal]

[DESIGNABLE bool]

[SCRIPTABLE bool]

[STORED bool]

[USER bool]

[CONSTANT]

[FINAL])

Пример:

Q_PROPERTY(bool focus READ hasFocus)

Q_PROPERTY(bool enabled READ isEnabled WRITE setEnabled)

Page 12: C++ STL & Qt. Занятие 03

http://www.slideshare.net/IgorShkulipa 12

Свойства в Qtclass ExampleClass1 : public QObject

{

Q_OBJECT

Q_PROPERTY(

QString Priority READ getPriority WRITE setPriority)

private:

QString priority;

public:

ExampleClass1(QObject *parent = 0);

~ExampleClass1();

void setPriority(QString prior);

QString getPriority();

};

void ExampleClass1::setPriority(QString prior) {

this->priority= prior;

}

QString ExampleClass1::getPriority() {

return this->priority;

}

Page 13: C++ STL & Qt. Занятие 03

http://www.slideshare.net/IgorShkulipa 13

Использование

#include "exampleclass1.h"

#include <QApplication>

int main(int argc, char *argv[])

{

QApplication a(argc, argv);

MainWindow w;

w.show();

ExampleClass1 exc1(NULL);

exc1.setProperty("Priority", "High");

return a.exec();

}

Page 14: C++ STL & Qt. Занятие 03

http://www.slideshare.net/IgorShkulipa 14

Q_ENUMS

Данный макрос регистрирует один или несколько типов перечислений вметаобъектной системе.

class ExampleClass1 : public QObject

{

Q_OBJECT

Q_PROPERTY

(Priorities Priority READ getPriority WRITE setPriority)

Q_ENUMS(Priorities)

private:

Priorities priority;

public:

ExampleClass1(QObject *parent = 0);

~ExampleClass1();

void setPriority(Priorities prior);

Priorities getPriority();

enum Priorities {High, Low, VeryHigh, VeryLow};

};

Page 15: C++ STL & Qt. Занятие 03

http://www.slideshare.net/IgorShkulipa 15

Использование

void ExampleClass1::setPriority(Priorities prior) {

this->priority= prior;

}

Priorities ExampleClass1::getPriority() {

return this->priority;

}

int main(int argc, char *argv[])

{

QApplication a(argc, argv);

MainWindow w;

w.show();

ExampleClass1 exc1(NULL);

exc1.setProperty("Priority", "High");

exc1.setProperty("Priority", ExampleClass1::High);

return a.exec();

}

Page 16: C++ STL & Qt. Занятие 03

http://www.slideshare.net/IgorShkulipa 16

Добавление дополнительной информации в класс

Прикреплённые к системе свойств дополнительным макросом,Q_CLASSINFO(), который может использоваться для присоединениядополнительных пар имя--значение к мета-объекту класса, например:

Q_CLASSINFO("Version", "3.0.0")

Как и другие мета-данные, информация класса доступна во времявыполнения через мета-объект.

Page 17: C++ STL & Qt. Занятие 03

http://www.slideshare.net/IgorShkulipa 17

Варианты

Объединение (union) в C и C++ – это структура, все члены которойрасполагаются по одному и тому же адресу. Таким образом, подобъединение отводится столько места в памяти, сколько занимает егонаибольший член. Никакого контроля за тем, что находится вобъединении не ведется, и его членами не могут быть объекты классасо специальным конструктором, деструктором, либо операциейкопирования.

Варианты, реализованные через класс QVariant, могут хранитьодновременно одно значение определенного типа, но являются болееудобными и безопасными, а также не предполагают жесткихограничений, как объединения.

Page 18: C++ STL & Qt. Занятие 03

http://www.slideshare.net/IgorShkulipa 18

Пользовательские типы в вариантах

Для хранения пользовательских типов используется класс QMetaType.Размещенные в QVariant типы должны регистрироваться через макросQ_DECLARE_METATYPE:

namespace Namespace1

{

struct Struct1

{

int value1;

char value2;

};

}

Q_DECLARE_METATYPE(Namespace1::Struct1)

// ...

Namespace1::Struct1 st1;

st1.value1 = 123;

st1.value2 = 'a';

QVariant var;

var.setValue<Namespace1::Struct1>(st1);

// ...

Namespace1::Struct1 st2 = var.value<Namespace1::Struct1>();

var.typeName(); // Namespace1::Struct1

Page 19: C++ STL & Qt. Занятие 03

http://www.slideshare.net/IgorShkulipa 19

Контейнеры в Qt

QVector<T> – это обычный динамический массив. Его имеет смыслиспользовать, если элементы должны храниться в одном участкепамяти.

QList<T> – наиболее часто используемый контейнер. Вставка элементовв середину списка осуществляется за O(n). Для вставки за постоянноевремя в Qt имеется связный список QLinkedList.

QLinkedList<T> – связный список. Он отличается от QList<T> тем, чтопри работе для доступа к элементам нужно использовать итераторы.При этом вставка элементов в середину происходит за постоянноевремя O(1) и не приводит к порче итератора, указывающего нанекоторый другой элемент. Доступ по индексу осуществляется за O(n).

Стек QStack<T> реализован через наследование от QVector<T> сдобавлением методов доступа к стеку.

Очередь QQueue<T> реализована через наследование от QList<T> сдобавлением методов head, enqueue, dequeue.

Page 20: C++ STL & Qt. Занятие 03

http://www.slideshare.net/IgorShkulipa 20

Контейнеры с доступом по ключу

QHash<K,T> – хэш-таблица, отображающая ключи типа K в значениятипа T.

QMultiHash<K,T> наследует QHash<K,T> и ориентирован на структуры,в которых одному ключу может соответствовать несколько значений.

QMap<K,T> – ассоциативный массив, отображающий ключи типа K взначения типа T.

QMultiMap<K,T> наследует QMap<K,T> и ориентирован на структуры, вкоторых одному ключу может соответствовать несколько значений.

QSet<T> – неупорядоченное множество, основанное на хэш-таблице.Множество позволяет быстро получать и добавлять значения

Множества

Page 21: C++ STL & Qt. Занятие 03

http://www.slideshare.net/IgorShkulipa 21

Указатели

Когда объект, на который ссылается указатель, разрушается, указательстановится «повисшим», т.е. содержащим адрес, по которому уже нетобъекта. Это часто служит источником ошибок.

В Qt имеется защищенный указатель QPointer<T>, которыйавтоматически принимает значение 0 при разрушении связанного сним объекта. Объект должен наследовать от QObject.

В остальном QPointer<T> работает как T*. Он автоматически приводитсяк T*, перегружаются операторы * и -> для разыменования, а такжеприсваивание =.

Конструкторы QPointer<T>:

QPointer();

QPointer (T *p);

QPointer (const QPointer<T> &p);

Page 22: C++ STL & Qt. Занятие 03

http://www.slideshare.net/IgorShkulipa 22

Жесткие ссылки

Обычный указатель типа T* можно «обернуть» в объектQSharedPointer<T>, который послужит жесткой ссылкой. Указательбудет удален в тот момент, когда последняя ссылка выйдет за областьдействия, и для нее будет вызван деструктор QsharedPointer<T>.Такая ссылка конструируется из обычного указателя:

QSharedPointer<Class1> sp0(new Class1);

Если указатель на объект передан конструктору QSharedPointer<T>, тообъект нельзя самостоятельно уничтожать либо создавать из него ещеодин QSharedPointer<T>. Новые жесткие ссылки создаются черезкопирование и присваивание.

Page 23: C++ STL & Qt. Занятие 03

http://www.slideshare.net/IgorShkulipa 23

Слабые ссылки

Для слабых ссылок QWeakPointer<T> не задано разыменование. Ониприменяются только для того чтобы проверить, не был ли указательудален. Аналогично, имеется метод isNull(), приведение к bool иоператор !. Слабые ссылки можно копировать, присваивать исравнивать.

Допускается преобразование жесткой ссылки в слабую и наоборот:

QWeakPointer<T> QSharedPointer::toWeakRef() const;

QSharedPointer<T> QWeakPointer::toStrongRef() const;

Page 24: C++ STL & Qt. Занятие 03

http://www.slideshare.net/IgorShkulipa 24

Итераторы

Итераторы в стиле STL эффективно реализованы, и через них работаюталгоритмы <QtAlgorithms>.

В каждом контейнере есть два типа итераторов: const_iterator сдоступом только для чтения и iterator с доступом для чтения и записи

Контейнер Итератор для чтенияИтератор для чтения и

записи

QList<T>, QQueue<T> QList<T>::const_iterator QList<T>::iterator

QLinkedList<T> QLinkedList<T>::const_iterator QLinkedList<T>::iterator

QVector<T>,

QStack<T>QVector<T>::const_iterator QVector<T>::iterator

QSet<T> QSet<T>::const_iterator QSet<T>::iterator

QMap<T>,

QMultiMap<T>QMap<T>::const_iterator QMap<T>::iterator

QHash<K,T>,

QMultiHash<K,T>QHash<K,T>::const_iterator QHash<K,T>::iterator

Page 25: C++ STL & Qt. Занятие 03

http://www.slideshare.net/IgorShkulipa 25

foreach

Для прохода по всем элементам контейнера в Qt имеется ключевое словоforeach.

QList<int> list;

list << 0 << 1 << 2 << 3;

foreach (int x, list)

{

qDebug() << x;

}

В foreach на каждом шаге числу x будет присваиваться значениеочередного элемента списка. При этом возможные изменения x небудут затрагивать содержимое списка. Для изменения содержимогонеобходимо использовать итераторы.

Page 26: C++ STL & Qt. Занятие 03

http://www.slideshare.net/IgorShkulipa 26

Обработка событий

События позволяют классу или объекту уведомлять другие классы илиобъекты о возникновении каких-либо ситуаций. Класс, отправляющий(или вызывающий) событие, называется издателем, а классы,принимающие (или обрабатывающие) событие, называютсяподписчиками.

Для связывания событий, происходящий с объектами, и функций,предназначенных для обработки этих событий, в библиотеке Qtиспользуется интересный механизм сигналов и слотов.

Сигнал - это сообщение о том, что произошло какое-либо событие,например, нажатие на кнопку или выбор пункта меню. Всяинформация о событии сохраняется в полях экземплярасоответствующего класса. У сигнала есть источник (например,кнопка) и приёмник (объект, метод которого будет обрабатывать этособытие).

Слот - это сама функция-обработчик события. Связь между всемичетырьмя перечисленными элементами задаётся с помощью методаconnect.

Page 27: C++ STL & Qt. Занятие 03

http://www.slideshare.net/IgorShkulipa 27

connect

bool QObject::connect (

const QObject *sender, // Источник события.

const char *signal, // Сигнал.

const QObject *receiver, // Объект-приёмник сигнала.

const char *method, // Функция-обработчик.

Qt::ConnectionType type = Qt::AutoConnection

) const

Последний параметр определяет режим обработки:

• Qt::DirectConnection -- событие обрабатывается сразу;• Qt::QueuedConnection -- событие ставится в общую очередь и

будет обработано только после всех сообщений, уже имеющихся вэтой очереди;

• Qt::AutoConnection -- если источник события находится в том жепотоке, что и приёмник, то будет использован режимQt::DirectConnection, в противном случае -- Qt::QueuedConnection.

Page 28: C++ STL & Qt. Занятие 03

http://www.slideshare.net/IgorShkulipa 28

Макросы SIGNAL и SLOT

Для определения сигнала и слота используются макросы SIGNAL и SLOT.

QObject::connect(

scrollBar, // Источник события.

SIGNAL(valueChanged(int)), // Сигнал.

label, // Объект-приёмник сигнала.

SLOT( setNum(int) ) ); // Функция-обработчик.

Параметрами сигнала и слота являются типы, а не переменные.

Количество параметров слота всегда не больше количествапараметров сигнала. Соответствие между ними, как обычно,позиционное: при выполнении программы значением i-го параметраслота становится значение i-го параметра сигнала.

В объявлении класса методы-слоты необходимо указывать в разделеpublic slots или private slots.

Если поместить их вместе с обычными методами класса, то программабудет скомпилирована без ошибок, но при её выполнениинеправильно объявленные методы-слоты вызываться не будут.

Page 29: C++ STL & Qt. Занятие 03

http://www.slideshare.net/IgorShkulipa 29

Сигналы

Обычно в программе используются стандартные сигналы, но еслитребуется определить собственные, то их надо объявить в разделеsignals.

class MainWondow : public QMainWindow {

Q_OBJECT

// ...

signals:

void mySignal(); // Сигнал.

private slots:

void onMySignal(); // Слот.

// ...

}

Page 30: C++ STL & Qt. Занятие 03

http://www.slideshare.net/IgorShkulipa 30

Соединение сигналов

Сигнал может быть соединён с другим сигналом, например:

connect( myButton,

SIGNAL( clicked() ),

this,

SIGNAL( buttonClicked() ) );

Один и тот же сигнал можно связать с несколькими слотами или другимисигналами.

С одним и тем же слотом можно связать несколько сигналов. Можноуказать несколько одинаковых "соединений": тогда одно событиевызовет генерацию нескольких сигналов и, соответственно,многократное выполнение метода-слота.

Чтобы разорвать связь между сигналом и слотом, используется методdisconnect:

bool QObject::disconnect ( const QObject *sender,

const char *signal,

const QObject *receiver,

const char *method );

Page 31: C++ STL & Qt. Занятие 03

http://www.slideshare.net/IgorShkulipa 31

Создание GUI приложение на Qt

Page 32: C++ STL & Qt. Занятие 03

http://www.slideshare.net/IgorShkulipa 32

Создание GUI приложение на Qt

Page 33: C++ STL & Qt. Занятие 03

http://www.slideshare.net/IgorShkulipa 33

Создание GUI приложение на Qt

Page 34: C++ STL & Qt. Занятие 03

http://www.slideshare.net/IgorShkulipa 34

Создание GUI приложение на Qt

Page 35: C++ STL & Qt. Занятие 03

http://www.slideshare.net/IgorShkulipa 35

Создание GUI приложение на Qt

Page 36: C++ STL & Qt. Занятие 03

http://www.slideshare.net/IgorShkulipa 36

Создание GUI приложение на Qt

Page 37: C++ STL & Qt. Занятие 03

http://www.slideshare.net/IgorShkulipa 37

Hello, Qt

Page 38: C++ STL & Qt. Занятие 03

http://www.slideshare.net/IgorShkulipa 38

main.cpp

Page 39: C++ STL & Qt. Занятие 03

http://www.slideshare.net/IgorShkulipa 39

mainwindow.h

Page 40: C++ STL & Qt. Занятие 03

http://www.slideshare.net/IgorShkulipa 40

mainwindow.cpp

Page 41: C++ STL & Qt. Занятие 03

http://www.slideshare.net/IgorShkulipa 41

Результат

Page 42: C++ STL & Qt. Занятие 03

http://www.slideshare.net/IgorShkulipa 42

Анимация виджетов

QAbstractAnimation Основа всех анимаций

QAnimationGroupАбстрактный базовый класс для групп анимаций

QEasingCurveУпрощение кривой (Easing curves) для управляемой анимации

QParallelAnimationGroup Параллельная группа анимаций

QPauseAnimation Пауза для QSequentialAnimationGroup

QPropertyAnimation Оживляет (Animates) свойства Qt

QSequentialAnimationGroup Последовательная группа анимаций

QTimeLineОтсечки времени (timeline) для управления анимацией

QVariantAnimationАбстрактный базовый класс для анимации

Page 43: C++ STL & Qt. Занятие 03

http://www.slideshare.net/IgorShkulipa 43

Пример

Page 44: C++ STL & Qt. Занятие 03

http://www.slideshare.net/IgorShkulipa 44

Результат

Page 45: C++ STL & Qt. Занятие 03

http://www.slideshare.net/IgorShkulipa 45

Графика в Qt

Ссылка

Основу используемых в Qt средств графики 2D составляет классQPainter.

Этот класс может использоваться для рисования геометрических фигур(точек, линий, прямоугольников, эллипсов, дуг, сегментов и секторовокруж ности, многоугольников и кривых Безье), а также пиксельныхкарт, изображени и текста. Кроме того, QPainter поддерживает такиепродвинутые функции, как сглаживание соединений линий(antialiasing) при начертании фигур и букв в тексте, аль фа-смешение(alpha blending), плавный переход цветов (gradient filling) и цепочкиграфических элементов (vector paths). QPainter также поддерживаетпреобразование координат, что делает графику 2D независимой отразрешающей способности.

В качестве альтернативы классам QPainter можно использовать OpenGIOpenGL является стандартной библиотекой графических средств 2D и3D. Модуль QtOpenGL позволяет очень легко интегрировать OpenGL вприложения Qt.

Page 46: C++ STL & Qt. Занятие 03

http://www.slideshare.net/IgorShkulipa 46

Лабораторная работа №3. GUI приложение на Qt