Launch a second view on a pushed button



  • Hey guys,

    I am new with Qt and i have a problem.
    I try to make a nice interface and my interface has tow view. First one is launch from main. First view has a button that launch a process (QProces) and after the process is finished it start the second view.
    Now i wold like when the process launch also start a new view with a progress bar.

    Right now i don't really want the process bar to reflect the real time that takes the process the finish. I just want to be able to start them at once.

    In main i have something like this :

        QQuickView firstview;
        view.setSource(QUrl("qrc:/firstView.qml"));
        view.setResizeMode(QQuickView::SizeRootObjectToView);
        firstview.show();
    

    My QML for progress bar looks like this:

    import QtQuick 2.3
    import QtQuick.Controls 1.4
    Item{
        ProgressBar {
            id: pb1
            minimumValue: 0
            maximumValue: 100
            value: 0
        }
    
        // Timer to show off the progress bar
        Timer {
            id: simpletimer
            interval: 100
            repeat: true
            running: true
            onTriggered: pb1.value < pb1.maximumValue ? pb1.value += 1.0 : pb1.value = pb1.minimumValue
        }
    }
    

    If i replace in main firstview.qml with loding.qml it works.
    But if i add them in the method that handle the pushed button it popup an empty window.
    My button handle looks like this:

    void Test::Butt() {
        this->proc->start("some_executabele", QIODevice::ReadWrite);
        this->proc->waitForFinished(-1);
    }
    

    If i modify the function like this

        view->setSource(QUrl("qrc:/loading.qml"));
        view->setResizeMode(QQuickView::SizeRootObjectToView);
        view->show();
        this->proc->start("some_executabele", QIODevice::ReadWrite);
        this->proc->waitForFinished(-1);
    

    The output is something like this:
    alt text
    While if i run the some code from main:

        QQuickView view;
        view.setSource(QUrl("qrc:/test.qml"));
        view.setResizeMode(QQuickView::SizeRootObjectToView);
        view.show();
    

    The output looks like this:
    alt text

    Can somebody give me a clue, why doesn't load ok the qml file when is call from button handler? :D
    Thx :)



  • Please...any idea are welcome. :(


  • Qt Champions 2016

    @Lucian said in Launch a second view on a pushed button:

    this->proc->start("some_executabele", QIODevice::ReadWrite);
    this->proc->waitForFinished(-1);

    If you remove this from void Test::Butt()
    does it work then ?



  • Hey @mrjj ,
    I have also try this but doesn't work eider. :(


  • Qt Champions 2016

    @Lucian

    ok can u try

    QQuickView * view = new QQuickView(this)
    view->setSource(QUrl("qrc:/test.qml"));
    view->setResizeMode(QQuickView::SizeRootObjectToView);
    view->show();

    (it leaks but , just for test)



  • No @mrjj
    Still have the same problem. I can't solve this thing. (


  • Qt Champions 2016

    @Lucian
    Ok then its not a variable running out of scope.

    And you have tested that
    Test::Butt()
    is called?

    Also try
    QQuickView * view = new QQuickView;
    instead of
    QQuickView * view = new QQuickView()

    Not sure if u want the view to be inside something or in a window.
    IF you dont give a Qwidget a parent it will become a window.
    Else its inserted into parent.

    Also the code

      QQuickView view;
        view.setSource(QUrl("qrc:/test.qml"));
        view.setResizeMode(QQuickView::SizeRootObjectToView);
        view.show();
    

    Can work from main but if u do the same in a function, you have this problem that
    as soon as functions ends, it will delete view
    so right after view.show(); is called it will be deleted. ( so might not show at all)
    That is why i showed
    QQuickView * view = new QQuickView(this)
    That wont run out of scope.



  • I have try everything, it doesn't work. Every time creates a new window but is empty.
    I don't understand why doesn't work..
    If i remove

    this->proc->start("some_executabele", QIODevice::ReadWrite);
    this->proc->waitForFinished(-1);
    

    Works ok...
    My function in pushed button now looks like this:

        QQuickView* view
        view = new QQuickView();
        view->setSource(QUrl("qrc:/loading.qml"));
        view->setResizeMode(QQuickView::SizeRootObjectToView);
        view->show();
        this->proc->start("some_executabele", QIODevice::ReadWrite);
        this->proc->waitForFinished(-1);
    

    Thank you for your help @mrjj


  • Qt Champions 2016

    @Lucian
    Hi
    It looks ok.
    ( Note, u create a new QQuickView each time. So its a leak but that u can fix later )

    I would look at what
    http://doc.qt.io/qt-5/qquickview.html#errors
    returns.

    To see if it has some issue running/loading.

    Update:
    Just to be sure. We are debugging the QQuickView and setSource
    and nothing related to waitForFinished ?

    Or are you saying that it works until you use QProcess then windows is empty?



  • Yes,,works until i use QProcess.
    If i let the button handle without QProcess it works.
    It is possible so lunch a QQuickView in a new QProcess? Maybe current process is the reason why doesn't work .


  • Qt Champions 2016

    @Lucian

    Then i think is what happens.
    The setSource starts to load. its still loading when functions returns.

    then waitForFinished blocks the event loop
    so there is no time to draw when the QML is ready.

    so I would try to use the
    http://doc.qt.io/qt-5/qquickview.html#statusChanged

    and if status is ready, then there in that slot i would run the QProcess.

    In that way you first block the event loop when the
    QML is 100% finished loading and that should work better.



  • Ok, i will try to find an example and i will post if i solve this.



  • Hey @mrjj

    Can you give me one last hand of help ?:D
    Look what i have done

    class Process : public QObject
    {
        Q_OBJECT
    private:
        QProcess* proc = new QProcess(this);
        QQuickView* view = new QQuickView();
    
    public slots:
        void startProcess();
    };
    

    In process.cpp

    void Process::startProcess()
    {
        this->proc->start("C:\\Windows\\System32\\calc.exe", QIODevice::ReadWrite);
        this->proc->waitForFinished(-1);
    }
    
    void Process::run() {
        view->setSource(QUrl("qrc:/loading.qml"));
        view->setResizeMode(QQuickView::SizeRootObjectToView);
        view->show();
    
        QObject::connect(view,SIGNAL(view::statusChanged),this, SLOT(Process::startProcess()));
    }
    

    Now the qml is show correct but doesn't start the calc.exe after the qml is load.
    Is corect how i use QObject::connect?


  • Qt Champions 2016

    @Lucian said in Launch a second view on a pushed button:

    Hi
    Good work
    There is a slight adjustment

    QObject::connect(view,SIGNAL(view::statusChanged),this, SLOT(Process::startProcess()));

    should be

    QObject::connect(view,SIGNAL(statusChanged() ),this, SLOT(startProcess() ) );
    ( no class:: in front when using the old syntax)

    And i would love if you did

    qDebug() << "status sig:" << QObject::connect(view,SIGNAL(statusChanged() ),this, SLOT(startProcess() ) );

    so you can check it says TRUE;

    Also
    void Process::startProcess() {
    qDebug() << "startProcess called";
    ...

    So we know it connects works and the startProcess is called.



  • Something is wrong.
    It say : "status sig: false"
    So the signal is not generated.

    Also say:
    QObject::connect: No such signal QQuickView::statusChanged()


  • Qt Champions 2016

    @Lucian
    ahh sorry.
    Didnt check the docs. ( shame on me)

    its just missing the parameter.

    void QQuickView::statusChanged(QQuickView::Status status)

    so its
    QObject::connect(view,SIGNAL(statusChanged(QQuickView::Status) ),this, SLOT(startProcess(QQuickView::Status) ) );

    NOte. only Type is added. NOT the paramtername

    and u need/could to change slot too

    void Process::startProcess( QQuickView::Status thesatus) {
    so here u can actually see if its ready etc.

    but u dont need to use the status :)


  • Moderators

    @Lucian
    Please check documentation: http://doc.qt.io/qt-5/qquickview.html#statusChanged
    The signal has a parameter, so it should be:

    qDebug() << "status sig:" << QObject::connect(view,SIGNAL(statusChanged(QQuickView::Status) ),this, SLOT(startProcess() ) );
    


  • Thanks @mrjj , @jsulm
    Now it's better.
    "status sig: true"

    But the startProcess() still isn't call yet.
    The message from slot is not printed and the calc.exe doesn't show up, but at lest the status from QQuickView is changed.


  • Moderators

    @Lucian Try to connect first:

    void Process::run() {
        QObject::connect(view,SIGNAL(view::statusChanged),this, SLOT(Process::startProcess()));
        view->setSource(QUrl("qrc:/loading.qml"));
        view->setResizeMode(QQuickView::SizeRootObjectToView);
        view->show();
    }


  • Yes @jsulm .
    It work but this doesn't solve my problem.
    I try to connect status change with startProcess because the progress bar (loading.qml) was block by waitForFinish(-1).
    Now is happening the same.
    The signal and the slot are called in the right order but also loading.qml doesn't popup until i close the calc.exe.


  • Moderators

    @Lucian Why do you wait for the process to finish?

    this->proc->waitForFinished(-1);
    

    Are you aware that this call blocks the event loop (so your app is blocked)?



  • Yes @jsulm .
    I need to do that because the process what will be launch will create a txt file. This file will be use farder so i need to be sore the process has finished his job and has created the txt.


  • Moderators

    @Lucian No need to wait for this! Just connect to http://doc.qt.io/qt-5/qprocess.html#finished signal - when it is called the process has finished...
    Qt is an asynchronous framework - you should adapt to asynchronous programming.



  • But how will wait my application to create the txt file ? Because after the process is finished i want to read from that .txt file created by him and if i read before creation the application will fail.
    So i need to connect the finish signal from QProcess with a slot that make the read from .txt file? :D


  • Moderators

    @Lucian Yes, you simply connect a slot to that signal and do what you want with that file in this slot.



  • I have made some changes and now look like this:

    void Process::startProcess()
    {
        qDebug() << "startProcess called";
        this->proc->start("C:\\Windows\\System32\\calc.exe", QIODevice::ReadWrite);
        qDebug() << "connect status :" << QObject::connect(proc,SIGNAL(QProcess::finished()),this, SLOT(addData()));
    }
    

    And the slot:

    void Process::addData()
    {
        qDebug() << "addData call:";
        SomeClasss c;    
        c.read();
    }
    

    The problem is again with type of the signal:
    *QObject::connect: No such signal QProcess::QProcess::finished()

    From documentation (Qt doc) doesn't seems to be something wrong.



  • I have solved the problem like this:

        qDebug() << "connect status :" << QObject::connect(proc,SIGNAL(finished(int, QProcess::ExitStatus)),this, SLOT(addData()));
    

    I will mark this as Solved.
    Thank you for your help @jsulm , @mrjj .


Log in to reply
 

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