Harrix Блог

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

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

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

21.03.2016 1 Comment 5 066 просмотров

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

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

Исходники

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

В отличии от статьи в данной статьи рассматривается построение приложение не с использованием чистого QML, а с использованием QtQuick Controls, то есть компонентов, которые похожи на стандартные компоненты из Qt Widgets и вообще из стандартных приложений. Но получается всё равно QML приложение со всеми плюсами.

В статье http://blog.harrix.org/?p=5079 рассказывается краткий алгоритм построения подобных приложений.

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

Содержание

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

Подготовка

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

2016-03-20_210516

2016-03-21_014337

2016-03-21_014400

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

2016-03-21_014418

2016-03-21_014434

2016-03-21_014444

2016-03-21_014556

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

2016-03-21_014606

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

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

2016-03-21_015135

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

2016-03-21_015339

2016-03-21_015403

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

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
property alias button1: button1
 
ColumnLayout {
anchors.centerIn: parent
 
Button {
id: button1
text: qsTr("Сложить")
}
 
TextInput {
id: textInput1
objectName: "textInput1"
width: 80
height: 20
text: qsTr("1")
font.family: "Times New Roman"
font.pixelSize: 12
}
 
TextInput {
id: textInput2
objectName: "textInput2"
width: 80
height: 20
text: qsTr("1")
font.pixelSize: 12
}
 
Text {
id: memo
objectName: "memo"
text: qsTr("")
font.pixelSize: 12
}
}

Получим такой код файла main.qml (я еще добавил один import):

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
import QtQuick 2.6
import QtQuick.Controls 1.5
import QtQuick.Layouts 1.1
 
ApplicationWindow {
visible: true
width: 640
height: 480
title: qsTr("Hello World")
 
property alias button1: button1
 
ColumnLayout {
anchors.centerIn: parent
 
Button {
id: button1
text: qsTr("Сложить")
}
 
TextInput {
id: textInput1
objectName: "textInput1"
width: 80
height: 20
text: qsTr("1")
font.family: "Times New Roman"
font.pixelSize: 12
}
 
TextInput {
id: textInput2
objectName: "textInput2"
width: 80
height: 20
text: qsTr("1")
font.pixelSize: 12
}
 
Text {
id: memo
objectName: "memo"
text: qsTr("")
font.pixelSize: 12
}
}
}

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

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

2016-03-21_015906

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

C++ часть

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

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

2016-03-21_020015

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

2016-03-20_212807

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

2016-03-21_020109

2016-03-21_020148

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

2016-03-21_020212

Начнем его редактирование. Перейдем вначале в заголовочный файл 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 в головном элементе ApplicationWindow добавим сигнал:

1
signal qmlSignal(string msg)

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

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

1
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
import QtQuick 2.6
import QtQuick.Controls 1.5
import QtQuick.Layouts 1.1
 
ApplicationWindow {
visible: true
width: 640
height: 480
title: qsTr("Hello World")
 
property alias button1: button1
 
signal qmlSignal(string msg)
 
ColumnLayout {
anchors.centerIn: parent
 
Button {
id: button1
text: qsTr("Сложить")
onClicked: qmlSignal("яблок")
}
 
TextInput {
id: textInput1
objectName: "textInput1"
width: 80
height: 20
text: qsTr("1")
font.family: "Times New Roman"
font.pixelSize: 12
}
 
TextInput {
id: textInput2
objectName: "textInput2"
width: 80
height: 20
text: qsTr("1")
font.pixelSize: 12
}
 
Text {
id: memo
objectName: "memo"
text: qsTr("")
font.pixelSize: 12
}
}
}

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

Теперь, перейдем в файл 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 <QApplication>
#include <QQmlApplicationEngine>
 
#include "handlersignals.h"
 
int main(int argc, char *argv[])
{
QApplication 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_021226

Вот и всё)


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

  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)
  4. Сложение двух чисел в Qt 5.6.0 на C++ (Qt Labs Controls)

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

© 2014 Harrix