Harrix Блог

  • Списки статей
    • Все статьи
    • IT
    • Qt
    • C++
    • Сложение двух чисел
    • Web программированиe
    • FAQ
    • Latex
    • Установка программ
    • Мифы
    • Видео
    • Про фото
  • Проекты
  • Harrix.org
  • RSS
  • Контакты

Сложение двух чисел в Qt 5.6.0 на C++ (Qt Quick)

В статье описывается создание приложения QML через Qt Quick 2.6 с выполнением кода на С++.

21.03.2016 5 комментариев 8 496 просмотров

В статье описывается создание приложения QML через Qt Quick 2.6 с выполнением кода на С++.

В качестве среды для разработки используется Qt 5.6.0 для Windows 64 bit под компилятор Visual Studio.

Исходники

У меня уже была статья на эту тему. Но эта более актуальная. В данной статье рассматривается другой способ соединения C++ и QML.

В статье http://blog.harrix.org/?p=5079 приведена сокращенная версия данной статьи.

В статье http://blog.harrix.org/?p=5082 рассказывается о подобном приложении, но с использованием компонентов QtQuick Controls.

Статья из цикла «Сложение двух чисел». Для меня минимальное освоение любой системы программирования начинается с возможности создания такой программы. Если можно написать приложение, в которой пользователь может ввести два числа, считать их, провести с ними какие-то действия, а потом вывести результат, то, значит, базовое владение имеется. И много задач именно из области программирования, алгоритмики можно будет решать, зная, как в конкретной системе программирования запрограммировать такую программу.

Содержание

  • Подготовка
  • Построение интерфейса
  • C++ часть

Подготовка

Создадим Qt Quick приложение.

2016-03-20_210516

2016-03-20_210535

2016-03-20_210603

Не рекомендую выбирать With ui.qml. По крайней мере не все функции QML с таким файлом работали. Либо я что-то делал не то.

2016-03-20_210633

2016-03-20_210650

2016-03-20_210709

2016-03-20_210735

И переведите разработку приложения в режим Release.

2016-03-21_004514

Построение интерфейса

Откроем файл main.qml:

2016-03-20_211113

Удалим элемент MouseArea и элемент Text. Они тут демонстрационные.

2016-03-20_211500

2016-03-20_211528

Добавим в основной элемент Window следующую конструкцию:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
Column {
spacing: 5
anchors.centerIn: parent;
 
//Кнопка
Rectangle {
id: button //Имя кнопки
 
//Размеры кнопки
width: 100
height: 30
 
//Цвет кнопки
color: "#0066ff"
 
//Текст кнопки
Text {
id: buttonLabel
text: "Сложить"
color: "#ffffff";
anchors.centerIn: parent;
}
 
//Действие мыши
MouseArea {
id: mouseArea1
anchors.fill: parent
hoverEnabled: true;
}
}
 
//Строка ввода первого числа
Rectangle {
id: textinputRect1 //Имя строки ввода
 
//Размеры строки ввода
width: 100
height: 18
 
//цвет строки ввода
color: "#ffffff"
 
TextInput {
id: textinput1
objectName: "textinput1"
color: "#0066ff";
selectionColor: "blue"
font.pixelSize: 12;
width: parent.width-4
anchors.centerIn: parent
focus: true
text:"1"
}
}
 
//Строка ввода второго числа
Rectangle {
id: textinputRect2 //Имя строки ввода
 
//Размеры строки ввода
width: 100
height: 18
 
//цвет строки ввода
color: "#ffffff"
 
TextInput {
id: textinput2
objectName: "textinput2"
color: "#0066ff";
selectionColor: "blue"
font.pixelSize: 12;
width: parent.width-4
anchors.centerIn: parent
focus: true
text:"1"
}
}
 
//Поле вывода
Rectangle {
id: memoRect //Имя поля вывода
 
//Размеры поле вывода
width: 100
height: 35
 
//Цвет поля вывода
color: "#ffffff"
 
TextEdit{
id: memo
color: "#0066ff"
objectName: "memo"
wrapMode: TextEdit.Wrap
width:parent.width;
readOnly:true
}
}
}

Получим такой код файла main.qml:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
import QtQuick 2.6
import QtQuick.Window 2.2
 
Window {
visible: true
Column {
spacing: 5
anchors.centerIn: parent;
 
//Кнопка
Rectangle {
id: button //Имя кнопки
 
//Размеры кнопки
width: 100
height: 30
 
//Цвет кнопки
color: "#0066ff"
 
//Текст кнопки
Text {
id: buttonLabel
text: "Сложить"
color: "#ffffff";
anchors.centerIn: parent;
}
 
//Действие мыши
MouseArea {
id: mouseArea1
anchors.fill: parent
hoverEnabled: true;
}
}
 
//Строка ввода первого числа
Rectangle {
id: textinputRect1 //Имя строки ввода
 
//Размеры строки ввода
width: 100
height: 18
 
//цвет строки ввода
color: "#ffffff"
 
TextInput {
id: textinput1
objectName: "textinput1"
color: "#0066ff";
selectionColor: "blue"
font.pixelSize: 12;
width: parent.width-4
anchors.centerIn: parent
focus: true
text:"1"
}
}
 
//Строка ввода второго числа
Rectangle {
id: textinputRect2 //Имя строки ввода
 
//Размеры строки ввода
width: 100
height: 18
 
//цвет строки ввода
color: "#ffffff"
 
TextInput {
id: textinput2
objectName: "textinput2"
color: "#0066ff";
selectionColor: "blue"
font.pixelSize: 12;
width: parent.width-4
anchors.centerIn: parent
focus: true
text:"1"
}
}
 
//Поле вывода
Rectangle {
id: memoRect //Имя поля вывода
 
//Размеры поле вывода
width: 100
height: 35
 
//Цвет поля вывода
color: "#ffffff"
 
TextEdit{
id: memo
color: "#0066ff"
objectName: "memo"
wrapMode: TextEdit.Wrap
width:parent.width;
readOnly:true
}
}
}
 
}

Обратите внимание, что для всех элементов, к которым вы потом захотите обращаться в С++, пропишите не только свойство id, но и свойство objectName со строковым значением совпадающим с id.

Кратко пробежимся по коду, который у нас получился. Все компоненты мы расположили в главном корневом Window. В нем находится компонент Column, который располагает находящиеся в нем компоненты в столбик (вертикальная разметка компонентов).

1
2
3
4
5
Column {
spacing: 5
anchors.centerIn: parent;
...
}

Внутри него находится четыре компонента Rectangle.

Первый имеет id равное button, и это обычная кнопка, а точнее закрашенный прямоугольник с текстом внутри и областью для воздействия мышью с id равным mouseArea1.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
//Кнопка
Rectangle {
id: button //Имя кнопки
 
//Размеры кнопки
width: 100
height: 30
 
//Цвет кнопки
color: "#0066ff"
 
//Текст кнопки
Text {
id: buttonLabel
text: "Сложить"
color: "#ffffff";
anchors.centerIn: parent;
}
 
//Действие мыши
MouseArea {
id: mouseArea1
anchors.fill: parent
hoverEnabled: true;
}
}

Второй и третий Rectangle содержит компонент TextInput, то есть строку для ввода информации. В них будем записывать два наших числа.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
//Строка ввода первого числа
Rectangle {
id: textinputRect1 //Имя строки ввода
 
//Размеры строки ввода
width: 100
height: 18
 
//цвет строки ввода
color: "#ffffff"
 
TextInput {
id: textinput1
objectName: "textinput1"
color: "#0066ff";
selectionColor: "blue"
font.pixelSize: 12;
width: parent.width-4
anchors.centerIn: parent
focus: true
text:"1"
}
}
 
//Строка ввода второго числа
Rectangle {
id: textinputRect2 //Имя строки ввода
 
//Размеры строки ввода
width: 100
height: 18
 
//цвет строки ввода
color: "#ffffff"
 
TextInput {
id: textinput2
objectName: "textinput2"
color: "#0066ff";
selectionColor: "blue"
font.pixelSize: 12;
width: parent.width-4
anchors.centerIn: parent
focus: true
text:"1"
}
}

В последнем четвертом Rectangle содержится поле для вывода текста: TextEdit.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
//Поле вывода
Rectangle {
id: memoRect //Имя поля вывода
 
//Размеры поле вывода
width: 100
height: 35
 
//Цвет поля вывода
color: "#ffffff"
 
TextEdit{
id: memo
color: "#0066ff"
objectName: "memo"
wrapMode: TextEdit.Wrap
width:parent.width;
readOnly:true
}
}

Если мы запустим приложение, то получим следующее:

2016-03-20_211941

Итак, мы описали интерфейс нашей программы.

C++ часть

При нажатии на кнопку пока ничего не происходит. Исправим это. Для начала установим взаимосвязь между QML моделью и C++ кодом. Для этого создадим класс, через которое будем осуществлять взаимодействие.

Правой кнопкой щелкнем по проекту и выбираем пункт Add New....

2016-03-20_212713

Там выбираем C++ Class.

2016-03-20_212807

Там вводим название нашего нового класса, например, HandlerSignals, также добавив подключение инклуда QObject и базовым классом объявляем QObject.

2016-03-20_213002

2016-03-20_213058

В итоге получаем наш класс:

2016-03-20_213253

Начнем его редактирование. Перейдем вначале в заголовочный файл handlersignals.h.

Мы будем создавать экземпляр нашего объекта и передавать в качестве родителя сцену QML объектов.

Подключите файл #include <QVariant>.

handlersignals.h

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
#ifndef HANDLERSIGNALS_H
#define HANDLERSIGNALS_H
 
#include <QObject>
#include <QVariant>
 
class HandlerSignals : public QObject
{
Q_OBJECT
public:
explicit HandlerSignals(QObject *parent = 0);
 
signals:
 
public slots:
};
 
#endif // HANDLERSIGNALS_H

handlersignals.cpp (без изменений)

1
2
3
4
5
6
#include "handlersignals.h"
 
HandlerSignals::HandlerSignals(QObject *parent) : QObject(parent)
{
 
}

Теперь можем добавить наш слот по обработке сигнала. Для примера мы передадим из сигнала текстовой фрагмент, который добавим в итоговое сообщение.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
void HandlerSignals::cppSlot(const QString &msg) {
 
//Найдем строки ввода
QObject* textinput1 = this->parent()->findChild<QObject*>("textinput1");
QObject* textinput2 = this->parent()->findChild<QObject*>("textinput2");
//Найдем поле вывода
QObject* memo = this->parent()->findChild<QObject*>("memo");
 
//Считаем информацию со строк ввода через свойство text
QString str1=(textinput1->property("text")).toString();
QString str2=(textinput2->property("text")).toString();
 
int a = str1.toInt();//Переведем строку в число
int b = str2.toInt();//Переведем строку в число
 
int c = a + b; //Вычисления наши
 
QString strResult=QString::number(c);//Переведем результат в строку
 
//Ну и наконец выведем в поле вывода нашу информацию
memo->setProperty("text", str1+" + "+str2+" = "+strResult+" "+msg);
}

Получим такие файлы:

handlersignals.h

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
#ifndef HANDLERSIGNALS_H
#define HANDLERSIGNALS_H
 
#include <QObject>
#include <QVariant>
 
class HandlerSignals : public QObject
{
Q_OBJECT
public:
explicit HandlerSignals(QObject *parent = 0);
 
signals:
 
public slots:
void cppSlot(const QString &msg);
};
 
#endif // HANDLERSIGNALS_H

handlersignals.cpp

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
#include "handlersignals.h"
 
HandlerSignals::HandlerSignals(QObject *parent) : QObject(parent)
{
 
}
 
void HandlerSignals::cppSlot(const QString &msg) {
 
//Найдем строки ввода
QObject* textinput1 = this->parent()->findChild<QObject*>("textinput1");
QObject* textinput2 = this->parent()->findChild<QObject*>("textinput2");
//Найдем поле вывода
QObject* memo = this->parent()->findChild<QObject*>("memo");
 
//Считаем информацию со строк ввода через свойство text
QString str1=(textinput1->property("text")).toString();
QString str2=(textinput2->property("text")).toString();
 
int a = str1.toInt();//Переведем строку в число
int b = str2.toInt();//Переведем строку в число
 
int c = a + b; //Вычисления наши
 
QString strResult=QString::number(c);//Переведем результат в строку
 
//Ну и наконец выведем в поле вывода нашу информацию
memo->setProperty("text", str1+" + "+str2+" = "+strResult+" "+msg);
}

В прошлом варианте данного материала (когда писал, например, для Qt 5.5.0) я регистрировал в QML экземпляр класса и вызывал методы-слоты класса. Но при этом QML становился привязан к С++ коду, что не есть хорошо. Поэтому сейчас поступим по другому. Мы в QML документе просто отправим сигнал, что нужно посчитать сумму двух чисел, а уже в С++ поймаем данный сигнал и отправим на обработку в класс.

Вначале отправим сигнал. В main.qml в головном элементе Window добавим сигнал:

1
signal qmlSignal(string msg)

Обратите внимание, что объявление сигнала надо добавлять именно в корневой элемент, иначе мы сигнал не найдем.

А в кнопке в области действия мыши пропишем уже отправку сигнала:

1
2
3
4
5
6
7
//Действие мыши
MouseArea {
id: mouseArea1
anchors.fill: parent
hoverEnabled: true;
onClicked: {qmlSignal("яблок")}
}

В итоге получим файл main.qml:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
import QtQuick 2.6
import QtQuick.Window 2.2
 
Window {
visible: true
 
signal qmlSignal(string msg)
 
Column {
spacing: 5
anchors.centerIn: parent;
 
//Кнопка
Rectangle {
id: button //Имя кнопки
 
//Размеры кнопки
width: 100
height: 30
 
//Цвет кнопки
color: "#0066ff"
 
//Текст кнопки
Text {
id: buttonLabel
text: "Сложить"
color: "#ffffff";
anchors.centerIn: parent;
}
 
//Действие мыши
MouseArea {
id: mouseArea1
anchors.fill: parent
hoverEnabled: true;
onClicked: {qmlSignal("яблок")}
}
}
 
//Строка ввода первого числа
Rectangle {
id: textinputRect1 //Имя строки ввода
 
//Размеры строки ввода
width: 100
height: 18
 
//цвет строки ввода
color: "#ffffff"
 
TextInput {
id: textinput1
objectName: "textinput1"
color: "#0066ff";
selectionColor: "blue"
font.pixelSize: 12;
width: parent.width-4
anchors.centerIn: parent
focus: true
text:"1"
}
}
 
//Строка ввода второго числа
Rectangle {
id: textinputRect2 //Имя строки ввода
 
//Размеры строки ввода
width: 100
height: 18
 
//цвет строки ввода
color: "#ffffff"
 
TextInput {
id: textinput2
objectName: "textinput2"
color: "#0066ff";
selectionColor: "blue"
font.pixelSize: 12;
width: parent.width-4
anchors.centerIn: parent
focus: true
text:"1"
}
}
 
//Поле вывода
Rectangle {
id: memoRect //Имя поля вывода
 
//Размеры поле вывода
width: 100
height: 35
 
//Цвет поля вывода
color: "#ffffff"
 
TextEdit{
id: memo
color: "#0066ff"
objectName: "memo"
wrapMode: TextEdit.Wrap
width:parent.width;
readOnly:true
}
}
}
 
}

Запустите приложение. Конечно, у вас кнопка не сработает пока, но вы сможете проверить написали всё верно или нет.

Теперь, перейдем в файл main.cpp, чтобы прописать создание экземпляра класса и связать его с нужными объектами.

Добавим заголовочный файл:

1
#include "handlersignals.h"

А в функции main после загрузки qml файла пропишем строчки:

1
2
3
4
5
6
QObject* root = engine.rootObjects()[0];
 
HandlerSignals *handlerSignals= new HandlerSignals(root);
 
QObject::connect(root, SIGNAL(qmlSignal(QString)),
handlerSignals, SLOT(cppSlot(QString)));

В первой строчке мы находим корневой объект в QML модели. Во второй строчке создаем экземпляр нашего класса. И в третьей строчке связываем наш слот из класса и сигнал из qml файла.

Теперь main.cpp выглядит вот так:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
#include <QGuiApplication>
#include <QQmlApplicationEngine>
 
#include "handlersignals.h"
 
int main(int argc, char *argv[])
{
QGuiApplication app(argc, argv);
 
QQmlApplicationEngine engine;
engine.load(QUrl(QStringLiteral("qrc:/main.qml")));
 
QObject* root = engine.rootObjects()[0];
 
HandlerSignals *handlerSignals= new HandlerSignals(root);
 
QObject::connect(root, SIGNAL(qmlSignal(QString)),
handlerSignals, SLOT(cppSlot(QString)));
 
return app.exec();
}

Если всё сделали правильно, то при запуск приложения и нажатия на кнопку получим следующее:

2016-03-21_010728

Кстати, если у вас в QML используется компонент со своими сигналами, то связь вы устанавливаете с ним. Например:

1
2
3
QObject* ob = root->findChild<QObject*>("flatButton");
QObject::connect(ob, SIGNAL(qmlSignalFlatButton(QString)),
handlerSignals, SLOT(cppSlot(QString)));

Вот и всё)


Статьи по теме:

  1. Сложение двух чисел в Qt 5.5.0 на C++ (Qt Quick)
  2. Сложение двух чисел в Qt 5.5.0 на C++ (Qt Quick Controls)
  3. Сложение двух чисел в Qt 5.6.0 на C++ (Qt Quick Controls)
  4. Сложение двух чисел в Qt 5.6.0 на C++ (Qt Labs Controls)

IT C++, Qt, QtQuick, Программа сложения двух чисел

© 2014 Harrix