c++qmlqt5.4

Integrate C++ and QML. Qt 5.4


I was reading the Qt documentation for the past couple of hours trying to figure out a way to make a UI created with Qt Quick UI (QML) communicate (interact) with C++ code (functions... etc.).

I've read the 5 or 6 similar questions on here to but I'm kind of confused, I have problems figuring out where to start or what to do first. I'd appreciate it a lot if someone could take the time and list the steps needed to make this work.

What i've done so far. I tried doing ...>add new Item> C++ class but I failed with an error saying:" failed to add one or more files to project"> It seems like the files (.. .cpp and .h) are created, they were in the folder where the other project files were but not included in the project. What I wanna do is just something simple like changing the text of the textedit through a C++ function or any other way possible.

//Test.qml (main.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"


    }

}

//Button.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
        }
    }

}

Thank you for taking the time to read this and/or any replies.


Solution

  • Using Qt 5.4.0 and Qt Creator 3.3.0, create New Project:

    1. Click New Project
    2. Qt Quick Application
    3. Click Choose...
    4. Name the project and select where to place it
    5. Click Next
    6. Select Qt Quick 2.4 from the drop-down menu
    7. Click Next
    8. Select desired Kit(s)
    9. Click Next
    10. Click Finish

    Now You should see open main.qml file with following code:

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

    Change it to:

    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 = "";
            }
        }
    
        //################
    }
    

    Add C++ Class to Your project:

    1. Right Mouse Click project name in Projects viewer
    2. Click Add New...
    3. Select C++ Class if not already selected
    4. Click Choose...
    5. In Class name filed enter "CppClass"
    6. Set Base class to QObject
    7. Click Next
    8. Click Finish

    Open cppclass.h and change it to:

    #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
    

    Open cppclass.cpp and change it to:

    #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>");
    }
    
    //################
    

    Open main.cpp and change it to:

    #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();
    }
    

    Run Your application, type some text to Input Field and click send.



    In response to Dynamic Remo comment here's another way to have QML and C++ communicate. This approach is based on C++ emitting a signal and QML acting upon it. Following is the code to get it working.


    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();
    }
    

    main.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()
        }
    }