Интегрируйте C++ и QML. Qt 5.4

Последние пару часов я читал документацию Qt, пытаясь найти способ заставить пользовательский интерфейс, созданный с помощью Qt Quick UI (QML), общаться (взаимодействовать) с кодом C++ (функциями... и т.д.).

Я прочитал 5 или 6 похожих вопросов здесь, но я немного запутался, у меня проблемы с выяснением, с чего начать или что делать в первую очередь. Я был бы очень признателен, если бы кто-нибудь мог найти время и перечислить шаги, необходимые для выполнения этой работы.

Что я сделал до сих пор. Я попытался сделать ... > добавить новый элемент > класс С++, но мне не удалось с ошибкой, говорящей: «не удалось добавить один или несколько файлов в проект»> Похоже, что файлы (.. .cpp и .h) созданы, они были в папке, где были другие файлы проекта, но не были включены в проект. То, что я хочу сделать, это просто что-то простое, например, изменить текст textedit с помощью функции C++ или любым другим возможным способом.

//Test.qml (основной.qml)

    import QtQuick 2.1
    import QtQuick.Window 2.0

Rectangle {
     id: rootRect
    width: Screen.width/2
    height: Screen.height/2
    color: "gray"


    Button{}

    Rectangle{
        id: textField
        width: 120
        height: 40
        color: "white"
        x:274; y: 61
        border.color: "blue"
        border.width: 4
        radius: 2

    }

    TextEdit {

        id: display
        x: 274
        y: 61
        width: 80
        height: 20
        text: qsTr("Text Edit")
        font.pixelSize: 22
        color: "black"
        anchors.centerIn: textField

    }

    Rectangle{
        id: inputField
        width: textField.width
        height: textField.height
        border.color: "green"
        border.width: 3
        color: "white"
        x: 140; y: 61
    }

    TextEdit{
        id: input
        color: "red"
        font.pixelSize: 30
        anchors.centerIn: inputField
        text: "Some Text"


    }

}

//Кнопка.cpl

import QtQuick 2.0
import QtQuick.Window 2.0


Item {

    property string defaultText: "New Text"


    Rectangle{
    id: button
    width: rootRect.width/6
    height: rootRect.height/8
    color: "black"
    x: 200; y: 200
    radius: 10

    }

    MouseArea{
        id: buttonClickArea
        width: 0
        anchors.rightMargin: 0
        anchors.bottomMargin: 0
        anchors.fill: button

        onClicked: {

                display.text = defaultText
        }
    }

}

Спасибо, что нашли время, чтобы прочитать это и / или любые ответы.


person hekri    schedule 13.12.2014    source источник
comment
Я не вижу никаких попыток написать часть C++. Что касается вашей ошибки - похоже, вы пытаетесь добавить файлы классов C++ в проект Qt Quick UI. Этот тип проекта содержит только часть QML и выполняется с помощью утилиты qmlscene. Вам нужно Qt Quick Application. После создания проекта вы получите готовый к использованию проект с файлами QML и C++. Итак, теперь вы можете добавить свой класс C++ в проект. См. документацию, чтобы узнать, как можно интегрировать плагин C++ в QML.   -  person folibis    schedule 14.12.2014
comment
Кстати, в QtQuick.Controls 1.3 уже есть Button элемент   -  person folibis    schedule 14.12.2014
comment
Почти то, что сказал @folibis: New File or Project... > Qt Quick Application. Там у вас есть классы QML и C++. Код, который вы нашли в других ответах, можно скопировать в эти источники.   -  person BaCaRoZzo    schedule 14.12.2014
comment
@BaCaRoZzo и флибис. Спасибо вам обоим за комментарии. Похоже, парень, у которого я пытался учиться, забыл упомянуть, что для интеграции C++ нам нужно создать приложение Qt Quick, потому что все остальные проекты он начал как Qt Quick UI (чистый QML). folibis У меня есть готовый код C++, я просто пытался найти способ связать его с пользовательским интерфейсом. Что касается документации, я нахожу ее довольно запутанной... например. в двух очень похожих примерах включены разные вещи... и т.д. Думаю, мне придется начать копать документацию с самого начала.   -  person hekri    schedule 14.12.2014
comment
Если вы можете связать два примера, мы можем попытаться помочь вам и/или указать на другие или более подробные примеры. :)   -  person BaCaRoZzo    schedule 14.12.2014
comment
@BaCaRoZzo Большое спасибо. Я разобрался с этой проблемой, но есть еще одна. Если бы вы могли посмотреть, было бы неплохо. :) stackoverflow.com/questions/27473173/   -  person hekri    schedule 14.12.2014


Ответы (1)


Используя Qt 5.4.0 и Qt Creator 3.3.0, создайте новый проект:

  1. Нажмите Новый проект
  2. Быстрое приложение Qt
  3. Щелкните Выбрать...
  4. Назовите проект и выберите, где его разместить
  5. Нажмите кнопку "Далее
  6. Выберите Qt Quick 2.4 в раскрывающемся меню.
  7. Нажмите кнопку "Далее
  8. Выберите нужный комплект(ы)
  9. Нажмите кнопку "Далее
  10. Нажмите Готово

Теперь вы должны увидеть открытый файл main.qml со следующим кодом:

import QtQuick 2.4
import QtQuick.Window 2.2

Window {
    visible: true
    MainForm {
        anchors.fill: parent
        mouseArea.onClicked: {
            Qt.quit();
        }

    }
}

Измените его на:

import QtQuick 2.4
import QtQuick.Window 2.2

//### New Code ###

import QtQuick.Controls 1.3

//################

Window {
    id: window1
    visible: true

    //### New Code ###

    width: 400
    height: 500

    TextArea {
        id: textArea
        readOnly: true
        anchors.bottom: textInput.top
        anchors.bottomMargin: 6
        anchors.right: parent.right
        anchors.rightMargin: 8
        anchors.left: parent.left
        anchors.leftMargin: 7
        anchors.top: parent.top
        anchors.topMargin: 7
    }

    TextField {
        id: textInput
        y: 470
        height: 23
        anchors.right: sendButton.left
        anchors.rightMargin: 6
        anchors.bottom: parent.bottom
        anchors.bottomMargin: 7
        anchors.left: parent.left
        anchors.leftMargin: 7
    }

    Button {
        id: sendButton
        x: 328
        y: 470
        width: 64
        height: 23
        text: qsTr("Send")
        anchors.bottom: parent.bottom
        anchors.bottomMargin: 7
        anchors.right: parent.right
        anchors.rightMargin: 8

        onClicked: {
            CppClass.sendMessage(textInput.text, textArea);
            textInput.text = "";
        }
    }

    //################
}

Добавьте класс C++ в свой проект:

  1. Щелкните правой кнопкой мыши имя проекта в средстве просмотра проектов.
  2. Нажмите Добавить новый...
  3. Выберите класс C++, если он еще не выбран
  4. Щелкните Выбрать...
  5. В поле «Имя класса» введите «CppClass».
  6. Установите базовый класс в QObject
  7. Нажмите кнопку "Далее
  8. Нажмите Готово

Откройте cppclass.h и измените его на:

#ifndef CPPCLASS_H
#define CPPCLASS_H

#include <QObject>

//### New Code ###

#include <QQuickItem>
#include <QQuickTextDocument>
#include <QTextDocument>

//################

class CppClass : public QObject
{
    Q_OBJECT
public:
    explicit CppClass(QObject *parent = 0);
    ~CppClass();

    //### New Code ###

    Q_INVOKABLE void sendMessage(const QString &msg, QQuickItem *textArea);

    //################

signals:

public slots:
};

#endif // CPPCLASS_H

Откройте cppclass.cpp и измените его на:

#include "cppclass.h"

CppClass::CppClass(QObject *parent) : QObject(parent)
{

}

CppClass::~CppClass()
{

}
//### New Code ###

void CppClass::sendMessage(const QString &msg, QQuickItem *textArea)
{
    QTextDocument *textDocument = textArea->property("textDocument").value<QQuickTextDocument*>()->textDocument();

    textDocument->setHtml(textDocument->toHtml() + "\n<b>Text sent to Cpp side:</b> <i>" + msg + "</i>");
}

//################

Откройте main.cpp и измените его на:

#include <QGuiApplication>
#include <QQmlApplicationEngine>

//### New Code ###

#include <QQmlContext>

#include "cppclass.h"

//################

int main(int argc, char *argv[])
{
    QGuiApplication app(argc, argv);

    QQmlApplicationEngine engine;

    //### New Code ###

    CppClass cppClass;

    engine.rootContext()->setContextProperty("CppClass", &cppClass);

    //################

    engine.load(QUrl(QStringLiteral("qrc:/main.qml")));

    return app.exec();
}

Запустите ваше приложение, введите текст в поле ввода и нажмите «Отправить».



В ответ на комментарий Dynamic Remo вот еще один способ взаимодействия QML и C++. Этот подход основан на том, что C++ выдает сигнал, а QML воздействует на него. Ниже приведен код, чтобы заставить его работать.


cppclass.h

#ifndef CPPCLASS_H
#define CPPCLASS_H

#include <QObject>

#include <QDateTime>

class CppClass : public QObject
{
    Q_OBJECT
public:
    explicit CppClass(QObject *parent = 0);
    ~CppClass();

    Q_INVOKABLE void getCurrentTime();

signals:
    void timeUpdate(QString currentTime);

public slots:
};

#endif // CPPCLASS_H

cppclass.cpp

#include "cppclass.h"

CppClass::CppClass(QObject *parent) : QObject(parent)
{

}

CppClass::~CppClass()
{

}

void CppClass::getCurrentTime()
{
    emit timeUpdate(QDateTime::currentDateTime().toString("ddd dd MMMM yyyy hh:mm:ss.zzz"));
}

main.cpp

#include <QGuiApplication>
#include <QQmlApplicationEngine>

#include <QQmlContext>

#include "cppclass.h"

int main(int argc, char *argv[])
{
    QGuiApplication app(argc, argv);

    CppClass cppClass;

    QQmlApplicationEngine engine;

    engine.rootContext()->setContextProperty("CppClass", &cppClass);

    engine.load(QUrl(QStringLiteral("qrc:/main.qml")));

    return app.exec();
}

основной.qml:

import QtQuick 2.4
import QtQuick.Window 2.2
import QtQuick.Controls 1.2

Window {
    id: rootWindow
    width: 400
    height: 400
    visible: true

    Connections {
        target: CppClass

        onTimeUpdate: {
            initailizeDllMsg.text = currentTime
        }
    }

    Text {
        id: initailizeDllMsg
        text: qsTr("{current time placeholder}")
        font.pointSize: 14
        anchors.horizontalCenter: parent.horizontalCenter
        anchors.verticalCenter: parent.verticalCenter
    }

    Button {
        id: button1
        x: 163
        y: 357
        text: qsTr("Show current time")
        anchors.bottom: parent.bottom
        anchors.bottomMargin: 20
        anchors.horizontalCenter: parent.horizontalCenter

        onClicked: CppClass.getCurrentTime()
    }
}
person Maz T    schedule 05.01.2015
comment
это очень помогает :) я могу понять этот доступ к TextArea и настройку текста из TextField. Можете ли вы также указать мне, как изменить текст для QML TEXT? Спасибо Вам!!! Текст {идентификатор: initailizeDllMsg текст: initailize_lbl} - person Dynamic Remo; 06.04.2016
comment
@DynamicRemo Я обновил свой ответ, чтобы показать, как добиться того, чего вы хотите. - person Maz T; 07.04.2016
comment
Большое спасибо. ты спас мой день - person HosSeinM; 10.11.2016