Custom QGraphicsItem not updating on QDialog form
-
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'sadvance()function, and is supposed to advance the scene by the given number of iterations.As per the Qt documentation I've reimplemented
boundingrect(),paint()andadvance(). 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 thatMyItem::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(); } -
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. -
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.@Christian-Ehrlicher, that solved the problem, thanks!