Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • Users
  • Groups
  • Search
  • Get Qt Extensions
  • Unsolved
Collapse
Brand Logo
  1. Home
  2. Qt Development
  3. General and Desktop
  4. Custom QGraphicsItem not updating on QDialog form
Forum Updated to NodeBB v4.3 + New Features

Custom QGraphicsItem not updating on QDialog form

Scheduled Pinned Locked Moved Solved General and Desktop
3 Posts 2 Posters 414 Views
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • D Offline
    D Offline
    donnpie
    wrote on last edited by
    #1

    I'm trying to learn how to do simple animation in Qt, but having a hard time wrapping my head around the whole QGraphicsView / QGraphicsScene / QGraphicsItem paradigm. I wrote a small program, which is supposed to plot a small dot on the screen and move it around in a random way. I have a QDialog containing a QGraphicsView. The QGraphicsView has an associated QGraphicsScene. I've subclassed QGraphicsItem to produce a custom graphic object class called MyShape. The Dialog class contains a function called advance(int iterations) which calls MyShape's advance() function, and is supposed to advance the scene by the given number of iterations.

    As per the Qt documentation I've reimplemented boundingrect(), paint() and advance(). I've based most of the code on VoidRealm's vid: Basic and Advanced Animation with the QGraphicsItem, but added a bunch of qDebug() statements so that I can see what the code does.

    The scene correctly updates after the Dialog constructor has executed. The problem is that the scene doesn't update while Dialog::update() is running. The funny thing is that MyItem::update() is called correctly, at least as far as I can see from the qDialog() statements.

    How do I get the scene to update after every iteration of the for loop in Dialog::update() ?

    Here's the code:

    #ifndef DIALOG_H
    #define DIALOG_H
    
    #include <QDialog>
    #include <chrono>
    #include <thread>
    #include <QMainWindow>
    #include <QGraphicsItem>
    #include <QGraphicsScene>
    #include "myshape.h"
    
    using namespace std::this_thread;     // sleep_for, sleep_until
    using namespace std::chrono; // nanoseconds, system_clock, seconds
    
    namespace Ui {
    class Dialog;
    }
    class Dialog : public QDialog
    {
        Q_OBJECT
    public:
        explicit Dialog(QWidget *parent = nullptr);
        ~Dialog();
        void advance(int iterations);
    private:
        Ui::Dialog *ui;
        QGraphicsScene *_scene;
        MyShape *_shape; //Custom shape object
    };
    #endif // DIALOG_H
    
    #include "dialog.h"
    #include "ui_dialog.h"
    
    Dialog::Dialog(QWidget *parent) :
        QDialog(parent),
        ui(new Ui::Dialog)
    {
        qDebug() << "MainWindow::MainWindow(QWidget *parent) start on " << this;
        ui->setupUi(this);
        this->setModal(true); //modeless
        ui->graphicsView->setScene(_scene);
        ui->graphicsView->setRenderHint(QPainter::Antialiasing);
    
        int shapeCount = 1;
        for (int i = 0; i < shapeCount; i++)
        {
        _scene = new QGraphicsScene;
            _shape = new MyShape;
            _scene->addItem(_shape);
        }
        qDebug() << "MainWindow::MainWindow(QWidget *parent) end on " << this;
    }
    
    Dialog::~Dialog()
    {
        qDebug() << "MainWindow::~MainWindow() start on " << this;
        delete ui;
        qDebug() << "MainWindow::~MainWindow() end on " << this;
    }
    
    void Dialog::advance(int iterations)
    {
        qDebug() << "void MainWindow::advance(int iterations) start on " << this;
        for (int i = 0; i < iterations; i++)
        {
            _scene->advance();
            sleep_for(milliseconds(1000));
        }
        qDebug() << "void MainWindow::advance(int iterations) end on " << this;
    }
    
    
    #ifndef MYSHAPE_H
    #define MYSHAPE_H
    #include "QGraphicsItem"
    #include <QPainter>
    #include <QDebug>
    
    class MyShape : public QGraphicsItem
    {
    public:
        MyShape();
        QRectF boundingRect() const;
        void paint(QPainter *painter, const QStyleOptionGraphicsItem *option,
                         QWidget *widget);
    protected:
        void advance(int phase);
    
    };
    
    #endif // MYSHAPE_H
    
    
    #include "myshape.h"
    
    MyShape::MyShape()
    {
        qDebug() << "MyShape::MyShape() start on " << this;
        setPos(0, 0);
        qDebug() << "MyShape::MyShape() end on " << this;
    }
    
    QRectF MyShape::boundingRect() const
    {
        qDebug() << "QRectF MyShape::boundingRect() const start on " << this;
        //qDebug() << "QRectF MyShape::boundingRect() const end on " << this;
        return QRectF(0, 0, 20, 20);
    }
    
    void MyShape::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)
    {
        qDebug() << "void MyShape::paint(QPainter *painter... start on " << this;
        QPointF currentPosition = pos();
        QPointF bottomRight(currentPosition);
        bottomRight.setX(bottomRight.x()+20);
        bottomRight.setY(bottomRight.y()+20);
        painter->drawEllipse(QRectF(currentPosition, bottomRight));
        qDebug() << "void MyShape::paint(QPainter *painter... end on " << this;
    }
    
    void MyShape::advance(int phase)
    {
        qDebug() << "void MyShape::advance(int phase) start on " << this << "with phase" << phase;
        QPointF currentPosition = pos();
        if (phase == 0) return;
        setPos(currentPosition.x()+qrand()%50, currentPosition.y()+qrand()%50);
        qDebug() << "void MyShape::advance(int phase) end";
    }
    
    code_text#include "dialog.h"
    #include <QApplication>
    
    int main(int argc, char *argv[])
    {
        QApplication a(argc, argv);
        Dialog w;
        w.show();
        w.advance(10);
        return a.exec();
    }
    
    1 Reply Last reply
    0
    • Christian EhrlicherC Online
      Christian EhrlicherC Online
      Christian Ehrlicher
      Lifetime Qt Champion
      wrote on last edited by
      #2

      You're blocking the main thread with your sleep_for() call - what do you expect then?
      Don't block the main thread but use a QTimer.

      Qt Online Installer direct download: https://download.qt.io/official_releases/online_installers/
      Visit the Qt Academy at https://academy.qt.io/catalog

      D 1 Reply Last reply
      3
      • Christian EhrlicherC Christian Ehrlicher

        You're blocking the main thread with your sleep_for() call - what do you expect then?
        Don't block the main thread but use a QTimer.

        D Offline
        D Offline
        donnpie
        wrote on last edited by
        #3

        @Christian-Ehrlicher, that solved the problem, thanks!

        1 Reply Last reply
        0

        • Login

        • Login or register to search.
        • First post
          Last post
        0
        • Categories
        • Recent
        • Tags
        • Popular
        • Users
        • Groups
        • Search
        • Get Qt Extensions
        • Unsolved