[SOLVED] Need help to integrate C++ and QML



  • Hi,

    I'm trying to develop an application using QtQuick for the UI and C++ for the interface, but I'm having trouble connecting both lands. So far I was able to follow the tutorials at http://qt-project.org/doc/qt-5.0/qtqml/qtqml-cppintegration-topic.html , but I don't fully understand what's going on. To complicate matters, a lot of Qt tutorials related to QML use different classes, (QQmlApplicationEngine instead of QQmlEngine and so forth). The documentation for these classes is not clear to me as to what their function is, so can someone explain to me what's the relationship between all these QQmlEngine, QQmlComponent, QQmlContext ?

    Sorry if I'm too generic on my question, but I really need to figure this out.
    Thanks in advance,
    Lgb.


  • Moderators

    Hi,

    Maybe it's easier to describe something specific you want to achieve, and then find solutions for it. Qt QML and Qt Quick are large modules -- you probably don't need most of what's within them.

    Also, since you're using QML for your GUI, you'd use high-level QQuick* classes on the C++ side, not low-level QQml* classes.

    Are you familiar with signals and slots? If you simply want to pass data between a QML GUI and your C++ engine, I'd imagine signals and slots are enough. My post on 28 September shows how to connect them: https://qt-project.org/forums/viewthread/33011/#144473



  • Hi JKSH,

    Thank you very much for your help! I was (still am) very confused with all these classes for integration between QML and C++ (I was having some problems because I was using 5.2 beta, which introduces another QtQuick2ControlsApplicationViewer, which does not seem to work as a QQuickView, and doesn't yet have any documentation.)

    But now, following your examples and (http://qt-project.org/doc/qt-4.8/qtbinding.html) I was able to make bothway interactions. Thank you very much for that.

    However, the connection between a signal in C++ and a slot in QML didn't work, so I'm using the item->setProperty("propertyName", value) instead.

    I'd like better to be able to connect a C++ signal to a QML slot, instead of setting a property, So could you help me find out what's wrong with my application? Below follows the code for main.cpp, main.qml and the object I'm using for the interaction, object.h :

    main.qml:
    @import QtQuick 2.0

    Rectangle {
    width: 360
    height: 360
    signal qmlSignal
    property alias setText: mainText.text

    Text {
        id: mainText
        text: qsTr("Hello World")
        anchors.centerIn: parent
    }
    MouseArea {
        anchors.fill: parent
        onClicked: {
            qmlSignal();
        }
    }
    
    function setText(newText) {
        mainText.text = newText
    }
    

    }@

    main.cpp:
    @int main(int argc, char *argv[])
    {
    QGuiApplication app(argc, argv);

    QtQuick2ApplicationViewer viewer;
    viewer.setMainQmlFile(QStringLiteral("qml/qt51/main.qml"));
    viewer.showExpanded();
    
    QQuickItem* item = viewer.rootObject();
    Object obj;
    obj.setItem(item);
    QObject::connect(item, SIGNAL(qmlSignal()),
                     &obj, SLOT(print()));
    QObject::connect(&obj, SIGNAL(sendText(QString)),
                     item, SLOT(setText(QString)));
    return app.exec();
    

    }@

    object.h:
    @class Object : public QObject
    {
    Q_OBJECT
    public:
    explicit Object(QObject parent = 0);
    void setItem(QQuickItem
    item) { m_item = item; }

    signals:
    void sendText(QString newText);

    public slots:
    void print() {
    qDebug() << "Calling C++ from QML works.";
    //emit sendText(changeText());
    m_item->setProperty("setMainText", changeText());
    }

    private: //functions
    QString changeText() {
    if (m_newText == "It works!") {
    m_newText = "Hello World.";
    } else {
    m_newText = "It works!";
    }
    return m_newText;
    }

    private:
    QString m_newText;
    QQuickItem* m_item;
    };@

    What I intended to do with this example was :
    When the MouseArea is clicked, signal qmlSignal() is emitted and is connected to Object::print() slot in C++ land. That slot will print a debug on the console and will further interact with QML to change the text being displayed.
    In a first moment I tried to create the function setText(newText) in QML, and connect the signal Object::sendText(QString) to that function. But , when running , the following message appears:

    @QObject::connect: No such slot QQuickRectangle_QML_0::setText(QString) in ../qt51/main.cpp:21@

    But the only way I could achieve it was from calling the item->setProperty() and creating a property alias in the QML.

    Can you find where the problem is?

    Thanks in advance,
    lgb.


  • Moderators

    You're welcome :)

    [quote](I was having some problems because I was using 5.2 beta, which introduces another QtQuick2ControlsApplicationViewer, which does not seem to work as a QQuickView, and doesn’t yet have any documentation.)[/quote]QtQuick2ControlsApplicationViewer is a convenience class, auto-generated by Qt Creator. It is not part of Qt itself. It exists solely to handle platform-specific paths (you can view the source code in your project).

    I'm surprised that it doesn't inherit QQuickView though.

    If, at project creation, you select "Qt Quick 2.0" instead of "Qt Quick Components 1.0", you will get the QtQuick2ApplicationViewer convenience class, which DOES inherit QQuickView.

    But anyway, you don't strictly need these convenience classes. For learning purposes, I found it easier to delete the convenience class and work with QQuickView directly.

    [quote]However, the connection between a signal in C++ and a slot in QML didn’t work

    ....
    @
    QObject::connect(&obj, SIGNAL(sendText(QString)),
    item, SLOT(setText(QString)));
    @
    [/quote]On the QML side, a slot is a JavaScript function.

    C++ differentiates between "int", "std::string", "bool", etc., but all of JavaScript's variables are declared as the "var" type. So, the slot is setText(QVariant), not setText(QString).



  • Hi,

    It finally works, I really appreciate your help!

    The problem I was having with Qt 5.2 was that bot that projects for QtQuick2 (Buil-in elements) and QtQuick Controls utilize an ApplicationWindow as a root object on the QML file. QQuickView does not seem to support it, and I just found a thread that explains it a little (http://qt-project.org/forums/viewthread/23020 ).
    Well, while using an ApplicationWindow would be desirable, it is not necessary and I can stick to the simpler Rectangle instead.

    Thank you very much for your help, JKSH, I had been struggling with these issues for like two weeks, now I think I can advance more on the project I'm working on (it would be a simple chat application for Desktop/Android, by the way).

    lgb.


  • Moderators

    You're welcome :) All the best with your project!

    By the way, perhaps there's something you can help me with. Is your chat app P2P over the Internet? How do you establish a connection? I'm trying to write a multiplayer board game (Desktop+Android too), but haven't figured out the best way to connect two players without a central server. Is UPnP the way to go?



  • Hi JKSH,

    For this school project, I'm assuming that both clients know each other's IP, so what I do is for the client to try to connect to the peer's IP, and if it doesn't succeed, it becomes the Server. Now the other peer is able to connect. I won't have much time to add much features and quality for this project, as I struggled too much trying to make it work for Android (so far without success) hehe.


Log in to reply
 

Looks like your connection to Qt Forum was lost, please wait while we try to reconnect.