Important: Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

`main.qml` loaded only after the execution of a function called after



  • Hello,
    I cross compiled Qt5.14.2 for my raspberry pi 4 and I am trying to create a Qt Quick application
    so this is what my mail.cpp file looks like

    include <QGuiApplication>
    #include <QQmlApplicationEngine>
    #include<QDebug>
    #include <QQmlEngine>
    #include<QQmlContext>
    #include"contacteur.h"
    #include"capteur.h"
    #include<QApplication>
    #include <QtWidgets>
    #include <QQuickView>
    #include <QtQml>
    #include<QTimer>
    #include<QObject>
    #include<cstdlib>
    
    int main(int argc, char *argv[])
    {
    
        QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
        QScopedPointer<Contacteur>contacteur (new Contacteur);
         QApplication app(argc, argv);
        QQmlApplicationEngine engine;
    
        Capteur capteur;
        qmlRegisterType<Capteur>("capteur", 1, 0, "Capteur");
    
        engine.load(QUrl(QStringLiteral("qrc:/main.qml")));
        if (engine.rootObjects().isEmpty())
            return -1;
    
        qDebug()<<"avant l'exution de la fct frein=" <<capteur.getFrein();
        capteur.changer_etat();
        qDebug()<<"apres l'exution de la fct frein="<< capteur.getFrein();
    
        engine.rootContext()->setContextProperty("contacteur" ,contacteur.data());   
    
        return app.exec();
    }
    

    I have created a new item with c++ class called Capteur and integrated it to QML.
    I am working on interfacing C++ class with the QML so for that I created and application called 'changer_etat()' this fuction containes a sleep fonction from QThread and changes one of the attributes off this class

    can someone please explain to me why is my main.qml loaded only after the execution of capteur.changer_etat() ends knowing that in the main.cpp the load function is on top of the changer_etat function?
    Thank you for helping

    this is what my capteur.h looks like

    #ifndef CAPTEUR_H
    #define CAPTEUR_H
    
    #include <QMainWindow>
    #include <QObject>
    #include <QWidget>
    #include<QTimer>
    
    class Capteur : public QMainWindow
    {
        Q_OBJECT
        Q_PROPERTY(int frein READ getFrein WRITE setFrein NOTIFY freinChanged)
    public:
        explicit Capteur(QWidget *parent = nullptr);
        int getFrein();
    void changer_etat();
    private:
        int m_frein;
        QTimer *timerFrein;
    private slots :
         void onTimeoutfrein ();/
    signals:
         void freinChanged(int);
    public slots:
         void setFrein(int T);
    };
    #endif // CAPTEUR_H
    

    this is what my capteur.cpp looks like

    #include "capteur.h"
    #include<QDebug>
    #include<cstdlib>
    #include<QThread>
    
    Capteur::Capteur(QWidget *parent) : QMainWindow(parent)
    {    timerFrein =new QTimer (this);
        timerFrein->setTimerType(Qt::PreciseTimer); 
        connect (timerFrein,SIGNAL(timeout()),this,SLOT(onTimeoutfrein()));
        timerFrein->start(3000);
        m_frein=1;
    }
    void Capteur::setFrein(int t)
    {    m_frein=t;
        emit freinChanged(t); }
    
    int Capteur::getFrein()
    {    return m_frein; }
    
    void Capteur::changer_etat()
    {     QThread::msleep(6000);
            if (getFrein()==0)
        {   setFrein(1);
                }
        else
               setFrein(0);
    }
    
    void Capteur::onTimeoutfrein()
    {  
       }
    
    

    and this is the part of my main.qml
    where I try to interface between both qml and C++

    Window {
        id: root
        visible: true
        width: 1024
        height: 600
        title: qsTr("Dashboard")
        color: "black"
    
        Capteur{
            id:valeur_capteurs
        }
    Rectangle{
            id:rect_frein_main
            x: 555
            y: 184
            width: 39
            height: 24
            color: "#00000000" // transparent
            opacity: 1.0 // frein à main levé
            Image {
                id: frein_main
                width: rect_frein_main.width
                height: rect_frein_main.height
                anchors.centerIn: rect_frein_main
                source: "images/b8.png"
            }
            states: [
                State {
                    name: "frein_main_levé"
                    when :(valeur_capteurs.frein == 1)
                    PropertyChanges {target: rect_frein_main; opacity:1.0}
                },
                State {
                    name: "frein_main_bas"
                    when :(valeur_capteurs.frein == 0)
                    PropertyChanges {target: rect_frein_main ; opacity:0.0 }
                }]
    }
    }
    

    It has been a while that I am trying to make it work and to see that qml and c++ are interacting, I also tryed to change the value of the attribut in the slot which is connected to the signal timeout of the timer but couldn't work .

    If you know please tell me what am I doing wrong?


  • Moderators

    Why do you say that main.qml is loaded after changer_etat()? How have you established it? I don't see how, from this code, you could reach such conclusion.

    In general, UI is shown after you call app.exec() and the event loop gets started. That might give an impression of things being executed out of order, but I fail to see how it applies to your case here.

    BTW. You are creating Capteur object twice: one (unused) in C++ and one (used) in QML. These 2 objects are completely separate and will contain different values. You call changer_etat() on object which you do not use in QML.


  • Moderators

    Why do you say that main.qml is loaded after changer_etat()? How have you established it? I don't see how, from this code, you could reach such conclusion.

    In general, UI is shown after you call app.exec() and the event loop gets started. That might give an impression of things being executed out of order, but I fail to see how it applies to your case here.

    BTW. You are creating Capteur object twice: one (unused) in C++ and one (used) in QML. These 2 objects are completely separate and will contain different values. You call changer_etat() on object which you do not use in QML.



  • @amina said in &#x60;main.qml&#x60; loaded only after the execution of a function called after:

    QThread::msleep(6000);

    In changer_etat there is QThread::msleep(6000); in the beggining I set it 1000 so just 1 s and I said that I will see the difference when executing the code because after this 1s in qml the opacity of the rectangle rect_frein_main has to change from 1.0 to 0.0 if every thing works fine , but no I didn't see any difference so I started to increase the sleep time .. I put it 6000 so 6s and after that I noticed that my application toked more time to show up.
    I added some qdebug in changer_etat() and in main .cppbefore and after calling this function and I noticed that my application shows up only after all these qdebug..

    Thank you for clarifying that, I will try to remove one of the two object maybe this is causing this problem


  • Moderators

    QThread::msleep(6000); you run this in main thread, so it will block your entire application for 6 seconds.


  • Moderators

    If you want to delay some action, use QTimer::singleShot() instead.



  • Thank you so much ! I am new to Qt

    I also tried this and I didn't now why my counter was incremented 2 times every time out ! now that you clarified that I had 2 objects everything make sense !Thank you

    int counter=0;
    void Capteur::onTimeoutfrein()
    {   counter++;
        qDebug() <<"time is up"<<counter;/
        if (getFrein()==0)
        {
            setFrein(1);
            qDebug() <<"le frein à main est levé" << getFrein();
        }
        else 
    {setFrein(0);
    
        qDebug() <<"le frein à main est bas" << getFrein();
    }
    }
    

Log in to reply