8

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.

hekri
  • 307
  • 3
  • 11
  • 2
    I don't see any attempt to write C++ part. As to you error - it looks like you try to add C++ class files to `Qt Quick UI` project. This type of project contains only QML part and runs with qmlscene utility. What you need is `Qt Quick Application`. After you project created you will get ready to use project with QML and C++ files. So now you can add you C++ class to the project. See [documentation](http://doc.qt.io/qt-5/qtqml-cppintegration-topic.html) to see how you can intergate C++ plugin into QML – folibis Dec 14 '14 at 06:35
  • 2
    Btw, there is already `Button` item in `QtQuick.Controls 1.3` – folibis Dec 14 '14 at 06:37
  • 1
    Pretty much just what @folibis said: `New File or Project... > Qt Quick Application`. There you have QML AND C++ classes. Code that you found on other answers can be copied in that sources. – BaCaRoZzo Dec 14 '14 at 10:54
  • @BaCaRoZzo and filibis. Thank you both for the comments. Seems like the guy i was trying to learn from forgot to mention that to integrate C++ we need to create a Qt Quick Application because all the other projects he started as Qt Quick UI (pure QML). folibis I've got the C++ code ready, was just trying to find a way to connect it with a UI. As for the documentation I find it pretty confusing...for ex. in two pretty similar examples there are different "things" included...etc. I guess i'll have to start digging the documentation from the beginning. – hekri Dec 14 '14 at 13:15
  • 1
    If you can link the two examples we can try to help you and/or point you to different, or more detailed, examples. :) – BaCaRoZzo Dec 14 '14 at 13:28
  • @BaCaRoZzo Thank You very much. I've got this problem sorted out but have another one. If you could have a look it'd be nice. :) http://stackoverflow.com/questions/27473173/what-to-include-to-make-this-qt-project-work – hekri Dec 14 '14 at 19:32

1 Answers1

17

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()
    }
}
Maz T
  • 1,184
  • 13
  • 18
  • this helps alot :) i can understand this accessing of TextArea and setting Text from the TextField. Can you also guide me how to change the text for QML TEXT? Thanking You!!! Text { id: initailizeDllMsg text: initailize_lbl } – Dynamic Remo Apr 06 '16 at 14:19
  • @DynamicRemo I've update my answer to show how to achieve what You want. – Maz T Apr 07 '16 at 12:20
  • Thank you so much. you saved my day – HosSeinM Nov 10 '16 at 20:29