Qt5 Tutorial QGraphicsView Animation - 2020
In this tutorial, we will learn animation with QGraphicsView.
This tutorial is a continuation of the previous turotial for QGraphicsView and QGraphicsScene and Customizing Items by inheriting QGraphicsItem. We'll do simple animation
Qt->Qt Gui Application:
We need to put GraphicsView into our dialog box:
Here is the header file, dialog.h:
#ifndef DIALOG_H #define DIALOG_H #include <QDialog> #include <QGraphicsScene> #include <QTimer> namespace Ui { class Dialog; } class Dialog : public QDialog { Q_OBJECT public: explicit Dialog(QWidget *parent = 0); ~Dialog(); private: Ui::Dialog *ui; QGraphicsScene *scene; QTimer *timer; }; #endif // DIALOG_H
Here we set the references to QGraphicsScene and QTimer as private members.
The implementation file (dialog.cpp) should look like this:
#include "dialog.h" #include "ui_dialog.h" Dialog::Dialog(QWidget *parent) : QDialog(parent), ui(new Ui::Dialog) { ui->setupUi(this); scene = new QGraphicsScene(this); ui->graphicsView->setScene(scene); // anti-aliasing ui->graphicsView->setRenderHint(QPainter::Antialiasing); // The bounding rectangle of the scene // The scene rectangle defines the extent of the scene. // It is primarily used by QGraphicsView // to determine the view's default scrollable area, // and by QGraphicsScene to manage item indexing. scene->setSceneRect(-150, -150, 300, 300); QLineF topLine(scene->sceneRect().topLeft(), scene->sceneRect().topRight()); QLineF leftLine(scene->sceneRect().topLeft(), scene->sceneRect().bottomLeft()); QLineF rightLine(scene->sceneRect().topRight(), scene->sceneRect().bottomRight()); QLineF bottomLine(scene->sceneRect().bottomLeft(), scene->sceneRect().bottomRight()); QPen myPen = QPen(Qt::red); scene->addLine(topLine, myPen); scene->addLine(leftLine, myPen); scene->addLine(rightLine, myPen); scene->addLine(bottomLine, myPen); timer = new QTimer(this); connect(timer, SIGNAL(timeout()), scene, SLOT(advance())); timer->start(100); } Dialog::~Dialog() { delete ui; }
The primary thing for the implementation is this line:
scene->setSceneRect(-150, -150, 300, 300);
It sets the scene rectangle; the bounding rectangle of the scene.
The scene rectangle defines the extent of the scene.
It is primarily used by QGraphicsView to determine the view's default scrollable area,
and by QGraphicsScene to manage item indexing.
Once the bounding box is set, we draw the rectangle. If we run the code now, we get:
As we see in the picture, we have QGraphicsView (graphicsView). Within the graphicsView we have QGraphicsScene (scene). We'll add items to the scene and only items within the bounding box, sceneRect will be displayed. Otherwise it will be clipped away.
The red box is the bounding box, and the rest of the implementation code is for that box.
We also made slot, advance() for the timeout() signal.
Let's make a class called MyItem:
As we see from the picture above, we need to work on the new MyItem class, such as boundingRect() and paint() for QGraphicsScene. Also, advance() and doCollision() for our animation.
I'll skip the details of animation (see files at the end of this tutorial).
We run the code with 20 items. When it collides with others, the color turns into red.
We can grab all files for the project: GraphicsViewAnimation.zip.
dialog.h:
// dialog.h #ifndef DIALOG_H #define DIALOG_H #include <QDialog> #include <QGraphicsScene> #include <QTimer> namespace Ui { class Dialog; } class Dialog : public QDialog { Q_OBJECT public: explicit Dialog(QWidget *parent = 0); ~Dialog(); private: Ui::Dialog *ui; QGraphicsScene *scene; QTimer *timer; }; #endif // DIALOG_H
dialog.cpp:
// dialog.cpp #include "dialog.h" #include "ui_dialog.h" #include "myitem.h" Dialog::Dialog(QWidget *parent) : QDialog(parent), ui(new Ui::Dialog) { ui->setupUi(this); scene = new QGraphicsScene(this); ui->graphicsView->setScene(scene); // anti-aliasing ui->graphicsView->setRenderHint(QPainter::Antialiasing); // // The bounding rectangle of the scene // The scene rectangle defines the extent of the scene. // It is primarily used by QGraphicsView // to determine the view's default scrollable area, // and by QGraphicsScene to manage item indexing. // void setSceneRect(qreal x, qreal y, qreal w, qreal h) scene->setSceneRect(-200, -200, 300, 300); QLineF topLine(scene->sceneRect().topLeft(), scene->sceneRect().topRight()); QLineF leftLine(scene->sceneRect().topLeft(), scene->sceneRect().bottomLeft()); QLineF rightLine(scene->sceneRect().topRight(), scene->sceneRect().bottomRight()); QLineF bottomLine(scene->sceneRect().bottomLeft(), scene->sceneRect().bottomRight()); QPen myPen = QPen(Qt::red); scene->addLine(topLine, myPen); scene->addLine(leftLine, myPen); scene->addLine(rightLine, myPen); scene->addLine(bottomLine, myPen); // adding items to the scene int itemCount = 20; for(int i = 0; i < itemCount; i++) { MyItem *item = new MyItem(); scene->addItem(item); } timer = new QTimer(this); connect(timer, SIGNAL(timeout()),scene, SLOT(advance())); timer->start(100); } Dialog::~Dialog() { delete ui; }
myitem.h:
// myitem.h #ifndef MYITEM_H #define MYITEM_H #include <QPainter> #include <QGraphicsScene> #include <QGraphicsItem> class MyItem : public QGraphicsItem { public: MyItem(); QRectF boundingRect() const; void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget); protected: void advance(int phase); private: qreal angle, speed; void doCollision(); }; #endif // MYITEM_H
myitem.cpp:
// myitem.cpp #include "myitem.h" MyItem::MyItem() { // random start rotation angle = (qrand() % 360); setRotation(angle); // set the speed speed = 5; // 5 pixels // random start position int startX = 0; int startY = 0; if(qrand() % 1) { startX = qrand() % 200; startY = qrand() % 200; } else { startX = qrand() % -100; startY = qrand() % -100; } setPos(mapToParent(startX, startY)); } QRectF MyItem::boundingRect() const { return QRect(0,0,20,20); } void MyItem::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget) { QRectF rect = boundingRect(); // basic collision detection if(scene()->collidingItems(this).isEmpty()) { // no collision QPen pen(Qt::green, 5); painter->setPen(pen); } else { // collision !!! QPen pen(Qt::red, 5); painter->setPen(pen); // set the position doCollision(); } painter->drawEllipse(rect); } void MyItem::advance(int phase) { if(!phase) return; QPointF location = this->pos(); setPos(mapToParent(0, -speed)); } void MyItem::doCollision() { // get a new position // change the angle with randomness if(qrand() % 1) { setRotation(rotation() + (180 + (qrand() % 10))); } else { setRotation(rotation() + (180 + (qrand() % -10))); } // check if the new position is in bounds QPointF newPoint = mapToParent(-(boundingRect().width()), -(boundingRect().width() + 2)); if(!scene()->sceneRect().contains((newPoint))) { // move back in bounds newPoint = mapToParent(0,0); } else { // set the new position setPos(newPoint); } }
Qt 5 Tutorial
- Hello World
- Signals and Slots
- Q_OBJECT Macro
- MainWindow and Action
- MainWindow and ImageViewer using Designer A
- MainWindow and ImageViewer using Designer B
- Layouts
- Layouts without Designer
- Grid Layouts
- Splitter
- QDir
- QFile (Basic)
- Resource Files (.qrc)
- QComboBox
- QListWidget
- QTreeWidget
- QAction and Icon Resources
- QStatusBar
- QMessageBox
- QTimer
- QList
- QListIterator
- QMutableListIterator
- QLinkedList
- QMap
- QHash
- QStringList
- QTextStream
- QMimeType and QMimeDatabase
- QFile (Serialization I)
- QFile (Serialization II - Class)
- Tool Tips in HTML Style and with Resource Images
- QPainter
- QBrush and QRect
- QPainterPath and QPolygon
- QPen and Cap Style
- QBrush and QGradient
- QPainter and Transformations
- QGraphicsView and QGraphicsScene
- Customizing Items by inheriting QGraphicsItem
- QGraphicsView Animation
- FFmpeg Converter using QProcess
- QProgress Dialog - Modal and Modeless
- QVariant and QMetaType
- QtXML - Writing to a file
- QtXML - QtXML DOM Reading
- QThreads - Introduction
- QThreads - Creating Threads
- Creating QThreads using QtConcurrent
- QThreads - Priority
- QThreads - QMutex
- QThreads - GuiThread
- QtConcurrent QProgressDialog with QFutureWatcher
- QSemaphores - Producer and Consumer
- QThreads - wait()
- MVC - ModelView with QListView and QStringListModel
- MVC - ModelView with QTreeView and QDirModel
- MVC - ModelView with QTreeView and QFileSystemModel
- MVC - ModelView with QTableView and QItemDelegate
- QHttp - Downloading Files
- QNetworkAccessManager and QNetworkRequest - Downloading Files
- Qt's Network Download Example - Reconstructed
- QNetworkAccessManager - Downloading Files with UI and QProgressDialog
- QUdpSocket
- QTcpSocket
- QTcpSocket with Signals and Slots
- QTcpServer - Client and Server
- QTcpServer - Loopback Dialog
- QTcpServer - Client and Server using MultiThreading
- QTcpServer - Client and Server using QThreadPool
- Asynchronous QTcpServer - Client and Server using QThreadPool
- Qt Quick2 QML Animation - A
- Qt Quick2 QML Animation - B
- Short note on Ubuntu Install
- OpenGL with QT5
- Qt5 Webkit : Web Browser with QtCreator using QWebView Part A
- Qt5 Webkit : Web Browser with QtCreator using QWebView Part B
- Video Player with HTML5 QWebView and FFmpeg Converter
- Qt5 Add-in and Visual Studio 2012
- Qt5.3 Installation on Ubuntu 14.04
- Qt5.5 Installation on Ubuntu 14.04
- Short note on deploying to Windows
Ph.D. / Golden Gate Ave, San Francisco / Seoul National Univ / Carnegie Mellon / UC Berkeley / DevOps / Deep Learning / Visualization