GraphicsScene frozen in Main Window (ui) Graphics view



  • Hey guys,

    I am sorry to ask something that will probably end up being simple, but I am so exhausted from sleeping poorly due to the semester wrapping up and I am having trouble figuring out exactly where the fault in this code is.

    Basically all I have done is merged the Colliding Mouse example (http://doc.qt.io/qt-5/qtwidgets-graphicsview-collidingmice-example.html) with a basic Mainwindow format GUI that I created. I am trying to use it as a working piece for a graphical simulation I am going to develop on my own. The problem is that while I can perfectly get the GraphicsScene to show up in the graphics view with all of the mice drawn, the scene is frozen and the mice do not move at all on their own like they do in the original program.

    Here is my code:

    mouse.h : http://pastebin.com/HsnsN7kc
    mainwindow.h: http://pastebin.com/DSaq3iMg
    mouse.cpp : http://pastebin.com/cLvbrt6U
    main.cpp :

    #include "mainwindow.h"
    #include <QApplication>
    #include <QDebug>
    #include <QtWidgets>
    #include <math.h>
    #include "mouse.h"
    
    
    int main(int argc, char *argv[])
    {
        QApplication a(argc, argv);
        MainWindow w;
        w.show();
    
        return a.exec();
    }
    

    mainwindow.cpp: http://pastebin.com/sUGBt7uP

    It definitely has something to do with the timer going out of scope or a similar issue that results in the timers "timeout" signal never being emitted since most of the timing logic is now in mainwindow.cpp instead of main.cpp, as the "advance()" slot/function that is part of the colliding mice example is never called. It seems this part of the programs functionality is broken:

    QTimer timer;
    QObject::connect(&timer, SIGNAL(timeout()), scene, SLOT(advance()));
    timer.start(1000 / 33);
    

    either the timer is being deleted or something else is happening so that the timeout signal is never sent. I determined this using the debugger. "advance()" is never reached.

    Even though I am pretty sure I know what the problem is, I am not totally sure what to do about it as I have no experience using the timers in Qt and have just started using Graphicsview/GraphicsScene. I may have a better shot at it tomorrow once I sleep more but I figured I'd post this asking for some advice before I hit the hay.

    Thanks for any information. It may just be I need to read up some documents on program flow, or something with timers/threading to fully see whats happening, but I am hoping its not too complicated.

    Thank you.



  • Your QTimer instance scope is limited to the constructor. You should do like this:

    QTimer* timer = new QTimer();
    QObject::connect(timer, SIGNAL(timeout()), scene, SLOT(advance()));
    timer->start(1000 / 33);
    

    In the current implementation, the timer is indeed deleted.



  • @oblivioncth said:

    I am so exhausted from sleeping poorly due to the semester wrapping up and I am having trouble figuring out exactly where the fault in this code is.

    I know that feeling!! :)

    You probably want to dynamically allocate a new QTimer, not create one the heap. eg:

    QTimer * timer = new QTimer(this);
    QObject::connect(timer, SIGNAL(timeout()), scene, SLOT(advance()));
    timer->start(1000 / 33);
    

    Cheers.



  • Ah, @JohanSolo beat me to it ;)


  • Qt Champions 2016

    @Paul-Colby
    You both beat me to it, however I like your solution better, as @JohanSolo's creates a memory leak.

    @oblivioncth
    Alternatively to what's already suggested, you can create your timer as a member of your main window and not worry about the deletion (same goes for your scene and the form). Like this:

    class MainWindow : public QMainWindow
    {
        Q_OBJECT
    
    private:
        Ui::MainWindow ui;
        QGraphicsScene scene;
        QTimer timer;
    };
    

    and in the cpp you just use them as regular objects:

    MainWindow::MainWindow(QWidget *parent)
        : QMainWindow(parent)
    {
        ui.setupUi(this);
        // ...
        scene.setSceneRect(-300, -300, 800, 600);
        scene.setItemIndexMethod(QGraphicsScene::NoIndex);
        // ... You just drop the local timer instance ...
        QObject::connect(&timer, SIGNAL(timeout()), &scene, SLOT(advance()));
        timer.start(1000 / 33);
    };
    

    Kind regards.



  • @JohanSolo said:
    -snip-
    @Paul-Colby said:
    -snip-
    @kshegunov said:
    -snip-

    Thanks to the three of you for offering solutions. I will probably try using kshegunov's first just for the simplicity of its usage once implemented. Basically seemed to be the issue of me not having much experience using classes and many source files in C++ as the last time I used it before this semester was the first time, so I would just put all of my code in main.ccp.


Log in to reply
 

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