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. -
@Christian-Ehrlicher, that solved the problem, thanks!