[Solved] Statechange in connection with QSerialPort



  • Hey everyone,

    I'm new to Qt and qml. Just wanted to ask if it is possible and how to connect a stateChanged with a QSerialPort. So I want my GUI to change the state when I receive information from a serial port. Tried something with signal-slot, but didn't work at all. I don't want a connection between the received information and the GUI. Just the statechange.
    I hope anyone is able to help me.



  • What state do you refer too?
    You could connect the dataBitsChanged signal to a slot and then set you GUI state? Or connect the error signal to a slot. Whenever the error is set/reset you could do something within the slot with the GUI?



  • Let's keep it simple. I've created two more states called "State1" and "State2" in my QML. I also connected a device to the serial port. The device does "something" and replies when its done. Now I want to integrate this reply into Qt with QSerialPort. When getting this reply in Qt, I want the mainstate to change to "State1". Afterwards using a QTimer to not change directly to "State2" but after 10 seconds. I hope I've answered your question. Otherwise, please tell me.

    Do you have an example for using the dataBitsChanged signal you mensioned?

    I'm not able to explain it any better. I'm sorry for my bad english.



  • How do you work with states in the Qt (not in the QML)? I know about QStateMachine but I imagine you are doing something else.

    Or do you just mean that you want to work out passing information between QML and Qt? Because if so, I think signals and slots is indeed the way to go - even if hooking it up needs extra attention:
    http://qt-project.org/doc/qt-5.0/qtqml/qtqml-cppintegration-interactqmlfromcpp.html#connecting-to-qml-signals



  • So if I see correctly, I have to use the method from

    http://qt-project.org/doc/qt-5.0/qtqml/qtqml-cppintegration-interactqmlfromcpp.html#connecting-to-qml-signals

    and change the QString/QVariant with a StateChange, right? Or do I have to set an if-loop connected with the value/string in the qml? Like this:
    @if (qmlSignal(string msg)=="Hallo")
    {
    mainwindow.state="State2";
    }@
    After defining the QString in cpp..

    I still don't really get it. But I hope, what I'm saying makes any sense to you.

    EDIT:
    Tried the Signal-Slot method like this
    main.cpp:
    @
    #include <QtGui/QGuiApplication>
    #include "qtquick2applicationviewer.h"
    #include <QDebug>

    class MyClass : public QObject
    {
    Q_OBJECT
    public slots:
    void cppSlot(const QString &msg) {
    qDebug() << "Called the C++ slot with message:" <<msg;
    }
    };

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

    QtQuick2ApplicationViewer viewer;
    viewer.setMainQmlFile&#40;QStringLiteral("qml/versuchstate/main.qml"&#41;);
    
    MyClass myClass;
    QObject::connect(mainwindow, SIGNAL(qmlSignal(QString)), &myClass, SLOT(cppSlot(QString)));
    
    viewer.showExpanded();
    
    return app.exec&#40;&#41;;
    

    }@

    main.qml

    @import QtQuick 2.2

    Rectangle {
    id:mainwindow
    signal qmlSignal (string msg)
    width: 360
    height: 360
    Text {
    text: qsTr("Hello World")
    anchors.centerIn: parent
    }
    MouseArea {
    anchors.fill: parent
    onClicked: {
    mainwindow.qmlSignal("Hello from QML")
    }
    }@

    But didn't work, because a build-problem appeared where the first argument of the function connect is not accepted.

    If you're wondering: I always try new methods within new projects to keep it first simple and if it works I import them to my bigger project.

    Do you have an idea what's going wrong?

    EDIT:
    I think I did it! But I have no idea why it works.
    Made a new headerfile:
    @#include <QObject>

    class MyClass : public QObject
    {
    Q_OBJECT

    public:
    MyClass();
    ~MyClass();

    signals:

    void stateChanged (const QString &newState);
    

    public slots:

    };@

    My new cpp-file:
    @#include <QtGui/QGuiApplication>
    #include "qtquick2applicationviewer.h"
    #include <QDebug>
    #include <QtCore>
    #include <QQuickItem>
    #include <QObject>
    #include "myclass.h"
    #include <QQmlContext>

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

    MyClass data;
    viewer.rootContext()->setContextProperty("myclassData", &data); 
    viewer.setMainQmlFile&#40;QStringLiteral("qml/versuchstate/main.qml"&#41;&#41;;
    
    const QString &newState ="";
    emit data.stateChanged(newState&#41;;
    
    
    viewer.showExpanded();
    
    return app.exec&#40;&#41;;
    

    }

    MyClass::MyClass()
    {
    }

    MyClass::~MyClass()
    {
    }@
    And my new QML-File:
    @import QtQuick 2.2

    Rectangle {
    id:mainwindow
    width: 360
    height: 360
    Text {
    id: labeltext
    text: qsTr("Hello World")
    anchors.centerIn: parent
    }
    Connections {
    target: myclassData
    onStateChanged: { mainwindow.state="State2" }
    }

    MouseArea {
        anchors.fill: parent
        onClicked: {        }
    
        Rectangle {
            id: rectangle1
            x: 124
            y: 123
            width: 200
            height: 200
            color: "#000000"
            opacity: 0
        }
    
        Text {
            id: text1
            x: 86
            y: 70
            text: qsTr("Text")
            font.pixelSize: 12
            opacity: 0
        }
    
    
    
    
    }
    states: [
        State {
            name: "State1"
    
            PropertyChanges {
                target: rectangle1
                opacity: 1
            }
    
        },
        State {
            name: "State2"
            PropertyChanges {
                target: rectangle1
                opacity: 1
            }
    
            PropertyChanges {
                target: text1
                text: qsTr("Buhu")
                opacity: 1
            }
        }
    ]
    

    }@

    I now would be very happy if anyone was able to explain me why it is working. :-)



  • OK let's start with why your first try didn't work. You cpp file wouldn't know the "mainwindow" rectangle by the ID since that lives in the QML. If you look carefully at that "Connecting to QML Signals" document you'd see you missed an important line:

    @QObject *item = view.rootObject();@

    That root object (basically the highest QML element) is what would emit the signal we connect to.

    As for the second part - the one that works - you created a working connection between the C++ and QML but it works in the opposite direction compared to your first try. That is indeed how to connect the QML to a signal that is emitted from the C++ code. If you want to emit a signal from the QML and connect to it the C++ code, the first way (with the use of the rootObject) is the way to go.



  • Alright, thanks for your advice. Got it.

    Back to the main problem:
    How do I now connect this with a QSerialPort, so that the C++ to QML connection only works when I receive data from a serial port device?



  • I don't know the specifics of your code - but generally - if you want something to happen in the QML based on something happening in the C++ layer, emit a signal from the C++ and handle it in the QML - as you did in your last edit of the post.



  • Ok, thank you! Thread can be marked as solved, please.



  • Yeah - you're the one to do it :) Edit your first post and you should be able to edit the title.


  • Moderators

    Just edit your first post and add [Solved] to the beginning of the title. Thanks!


Log in to reply
 

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