Harrix Блог

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

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

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

01.08.2016 14 комментариев 9 727 просмотров

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

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

Исходники

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

Содержание

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

Подготовка

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

2016-08-01_171831

2016-08-01_171844

2016-08-01_171921

2016-08-01_171938

2016-08-01_171944

2016-08-01_172011

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

2016-08-01_172902

По умолчанию создается в болванке три qml файла. Удалим два из них — они нам пока не нужны.

2016-08-01_173145

2016-08-01_173159

2016-08-01_173224

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

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

2016-08-01_173610

Заменим содержимое на следующее:

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
import QtQuick 2.7
import QtQuick.Controls 2.0
import QtQuick.Layouts 1.3
 
import QtQuick.Controls.Material 2.0
 
ApplicationWindow {
 
    visible: true
    width: 640
    height: 480
    title: qsTr("Сложение двух чисел")
 
    Material.theme: Material.Light
    Material.primary: Material.BlueGray
    Material.accent: Material.Teal
 
    Column {
        spacing: 10
        anchors.centerIn: parent
 
        TextField {
            id: field1
            objectName: "field1"
            placeholderText: "Введите первое число"
            width: 250
        }
 
        TextField {
            id: field2
            objectName: "field2"
            placeholderText: "Введите второе число"
            width: 250
        }
 
        Button {
            id: button
            text: qsTr("Сложить")
            width: 250
        }
 
        Text {
            text: "Ответ:"
            font.pixelSize: textArea.font.pixelSize
        }
 
        TextArea {
            id: textArea
            objectName: "textArea"
            wrapMode: TextArea.Wrap
            readOnly: true
            width: 250
        }
    }
}

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

Перейдите в файл .pro вашего проекта и добавьте там quickcontrols2 в строчке QT += qml quick:

2016-08-01_180038

Запустите проект:

2016-08-01_180116

2016-08-01_180129

Как видите, болванка приложения заработала, однако, Material дизайн в стилях отсутствует.

Перейдем в файл main.cpp. Подключите инклуд:

1
#include <QQuickStyle>

И пропишите строчку:

1
QQuickStyle::setStyle("Material");

В итоге у меня файл принял вид:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
#include <QGuiApplication>
#include <QQmlApplicationEngine>
#include <QQuickStyle>
 
int main(int argc, char *argv[])
{
    QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
    QGuiApplication app(argc, argv);
 
    QQuickStyle::setStyle("Material");
 
    QQmlApplicationEngine engine;
    engine.load(QUrl(QLatin1String("qrc:/main.qml")));
 
    return app.exec();
}

2016-08-01_180344

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

2016-08-01_180518

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

C++ часть

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

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

2016-08-01_181118

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

2016-08-01_181206

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

2016-08-01_181252

2016-08-01_181314

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

2016-08-01_181357

Начнем его редактирование. Перейдем вначале в заголовочный файл 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* field1 = this->parent()->findChild<QObject*>("field1");
QObject* field2 = this->parent()->findChild<QObject*>("field2");
//Найдем поле вывода
QObject* textArea = this->parent()->findChild<QObject*>("textArea");
 
//Считаем информацию со строк ввода через свойство text
QString str1=(field1->property("text")).toString();
QString str2=(field2->property("text")).toString();
 
int a = str1.toInt();//Переведем строку в число
int b = str2.toInt();//Переведем строку в число
 
int c = a + b; //Вычисления наши
 
QString strResult=QString::number(c);//Переведем результат в строку
 
//Ну и наконец выведем в поле вывода нашу информацию
textArea->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* field1 = this->parent()->findChild<QObject*>("field1");
    QObject* field2 = this->parent()->findChild<QObject*>("field2");
    //Найдем поле вывода
    QObject* textArea = this->parent()->findChild<QObject*>("textArea");
 
    //Считаем информацию со строк ввода через свойство text
    QString str1=(field1->property("text")).toString();
    QString str2=(field2->property("text")).toString();
 
    int a = str1.toInt();//Переведем строку в число
    int b = str2.toInt();//Переведем строку в число
 
    int c = a + b; //Вычисления наши
 
    QString strResult=QString::number(c);//Переведем результат в строку
 
    //Ну и наконец выведем в поле вывода нашу информацию
    textArea->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
51
52
53
54
55
56
57
58
import QtQuick 2.7
import QtQuick.Controls 2.0
import QtQuick.Layouts 1.3
 
import QtQuick.Controls.Material 2.0
 
ApplicationWindow {
 
    visible: true
    width: 640
    height: 480
    title: qsTr("Сложение двух чисел")
 
    Material.theme: Material.Light
    Material.primary: Material.BlueGray
    Material.accent: Material.Teal
 
    signal qmlSignal(string msg)
 
    Column {
        spacing: 10
        anchors.centerIn: parent
 
        TextField {
            id: field1
            objectName: "field1"
            placeholderText: "Введите первое число"
            width: 250
        }
 
        TextField {
            id: field2
            objectName: "field2"
            placeholderText: "Введите второе число"
            width: 250
        }
 
        Button {
            id: button
            text: qsTr("Сложить")
            width: 250
            onClicked: qmlSignal("яблок")
        }
 
        Text {
            text: "Ответ:"
            font.pixelSize: textArea.font.pixelSize
        }
 
        TextArea {
            id: textArea
            objectName: "textArea"
            wrapMode: TextArea.Wrap
            readOnly: true
            width: 250
        }
    }
}

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

Теперь, перейдем в файл 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
22
23
24
25
#include <QGuiApplication>
#include <QQmlApplicationEngine>
#include <QQuickStyle>
 
#include "handlersignals.h"
 
int main(int argc, char *argv[])
{
    QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
    QGuiApplication app(argc, argv);
 
    QQuickStyle::setStyle("Material");
 
    QQmlApplicationEngine engine;
    engine.load(QUrl(QLatin1String("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-08-01_185818

Кстати, если у вас в 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