(C++) How to StretchDraw an image?
February 24, 2017 · View on GitHub
(C++)
How to StretchDraw an image?
How to StretchDraw an image? is a QT FAQ especially encountered during games.
There are three ways to stretchdraw an image:
- rectangular blocky stretchdraw, like this image (png)
- square blocky stretchdraw, like this image (png)
- smooth stretchdraw, like this image (png)
- View a screenshot of 'CppQtStretchDraw' (png)
- Download the Qt Creator project 'CppQtStretchDraw' (zip)
Rectangular blocky stretchdraw
To perform a rectangular blocky stretchdraw, like this image (png), obtain a QPainter from a QWidget.
dialogblockyrect.h
#ifndef DIALOGBLOCKYRECT_H #define DIALOGBLOCKYRECT_H #include <boost/shared_ptr.hpp> #include <QDialog> struct QPaintEvent; struct QTimer; namespace Ui { class DialogBlockyRect; } class DialogBlockyRect : public QDialog { Q_OBJECT public: explicit DialogBlockyRect(QWidget *parent = 0); ~DialogBlockyRect(); protected: void changeEvent(QEvent *e); private: Ui::DialogBlockyRect *ui; boost::shared_ptr<QTimer> m_timer; void paintEvent(QPaintEvent*); private slots: void onTimer(); }; #endif // DIALOGBLOCKYRECT_H
dialogblockyrect.cpp
#include <cstdlib> #include <QPainter> #include <QPaintEvent> #include <QTimer> #include "dialogblockyrect.h" #include "ui_dialogblockyrect.h" DialogBlockyRect::DialogBlockyRect(QWidget *parent) : QDialog(parent,Qt::Window), ui(new Ui::DialogBlockyRect), m_timer(new QTimer) { ui->setupUi(this); //Connect and start the timer QObject::connect(m_timer.get(),SIGNAL(timeout()),this,SLOT(onTimer())); m_timer->start(1000); } DialogBlockyRect::~DialogBlockyRect() { delete ui; } void DialogBlockyRect::changeEvent(QEvent *e) { QDialog::changeEvent(e); switch (e->type()) { case QEvent::LanguageChange: ui->retranslateUi(this); break; default: break; } } void DialogBlockyRect::paintEvent(QPaintEvent*) { QPainter painter(this); QPixmap pixmap(5,5); QImage image = pixmap.toImage(); const int maxy = image.height(); const int maxx = image.width(); for (int y=0; y!=maxy; ++y) { for (int x=0; x!=maxx; ++x) { image.setPixel( QPoint(x,y), QColor(std::rand() % 255, std::rand() % 255, std::rand() % 255).rgb()); } } pixmap = pixmap.fromImage(image); painter.drawPixmap(ui->widget->rect(),pixmap); } void DialogBlockyRect::onTimer() { repaint(); }
Square blocky stretchdraw
To perform a square blocky stretchdraw, like this image (png), the visual widget QGraphicsView is used. A (blocky) rescaled QGraphicsPixmapItem does the trick.
dialogblockysquare.h
#ifndef DialogBlocky_H #define DialogBlocky_H #include <boost/shared_ptr.hpp> #include <QDialog> struct QGraphicsPixmapItem ; struct QGraphicsScene; struct QTimer; namespace Ui { class DialogBlockySquare; } class DialogBlockySquare : public QDialog { Q_OBJECT public: explicit DialogBlockySquare(QWidget *parent = 0); ~DialogBlockySquare(); protected: void changeEvent(QEvent *e); void resizeEvent(QResizeEvent*); private: Ui::DialogBlockySquare *ui; boost::shared_ptr<QGraphicsScene> m_scene; boost::shared_ptr<QGraphicsPixmapItem> m_sprite; boost::shared_ptr<QTimer> m_timer; private slots: void onTimer(); }; #endif // DialogBlocky_H
dialogblockysquare.cpp
#include <iostream> #include <boost/foreach.hpp> #include <QColor> #include <QGraphicsPixmapItem> #include <QGraphicsScene> #include <QPixmap> #include <QPoint> #include <QTimer> #include "dialogblockysquare.h" #include "ui_dialogblockysquare.h" DialogBlockySquare::DialogBlockySquare(QWidget *parent) : QDialog(parent,Qt::Window), //Allow resize of dialog ui(new Ui::DialogBlockySquare), m_scene(new QGraphicsScene), m_sprite(new QGraphicsPixmapItem), m_timer(new QTimer) { ui->setupUi(this); //Create a 5x5 (nonvisual) sprite m_sprite->setPixmap(QPixmap(5,5)); //Add the sprite to the (nonvisual) scene m_scene->addItem(m_sprite.get()); //Add the scene to the (visual) graphicsscene ui->graphicsView->setScene(m_scene.get()); //Create a timer to change the graphicsview QObject::connect(m_timer.get(),SIGNAL(timeout()),this,SLOT(onTimer())); m_timer->start(1000); onTimer(); } DialogBlockySquare::~DialogBlockySquare() { delete ui; } void DialogBlockySquare::changeEvent(QEvent *e) { QDialog::changeEvent(e); switch (e->type()) { case QEvent::LanguageChange: ui->retranslateUi(this); break; default: break; } } void DialogBlockySquare::resizeEvent(QResizeEvent*) { //Rescale the blocky image to fit the graphicsview const double scale_x = static_cast<double>(ui->graphicsView->width()) / static_cast<double>(m_sprite->pixmap().width()); const double scale_y = static_cast<double>(ui->graphicsView->height()) / static_cast<double>(m_sprite->pixmap().height()); m_sprite->setScale(std::min(scale_x,scale_y)); } void DialogBlockySquare::onTimer() { //Draw a new blocky image QImage image = m_sprite->pixmap().toImage(); const int maxy = image.height(); const int maxx = image.width(); for (int y=0; y!=maxy; ++y) { for (int x=0; x!=maxx; ++x) { image.setPixel(QPoint(x,y), QColor(std::rand() % 255, std::rand() % 255, std::rand() % 255).rgb()); } } m_sprite->setPixmap(m_sprite->pixmap().fromImage(image)); }
Smooth stretchdraw
To perform a smooth stretchdraw, like this image (png), the visual widget QLabel is used.
dialogsmooth.h
#ifndef DialogSmooth_H #define DialogSmooth_H #include <boost/shared_ptr.hpp> #include <QDialog> struct QTimer; namespace Ui { class DialogSmooth; } class DialogSmooth : public QDialog { Q_OBJECT public: explicit DialogSmooth(QWidget *parent = 0); ~DialogSmooth(); protected: void changeEvent(QEvent *e); private: Ui::DialogSmooth *ui; boost::shared_ptr<QTimer> m_timer; private slots: void onTimer(); }; #endif // DialogSmooth_H
dialogsmooth.cpp
#include <iostream> #include <boost/foreach.hpp> #include <QColor> #include <QPoint> #include <QTimer> #include "dialogsmooth.h" #include "ui_dialogsmooth.h" DialogSmooth::DialogSmooth(QWidget *parent) : QDialog(parent,Qt::Window), //Allow resize of dialog ui(new Ui::DialogSmooth), m_timer(new QTimer) { ui->setupUi(this); //Create a 5x5 image ui->label->setPixmap(QPixmap(5,5)); QObject::connect(m_timer.get(),SIGNAL(timeout()),this,SLOT(onTimer())); onTimer(); m_timer->start(1000); } DialogSmooth::~DialogSmooth() { delete ui; } void DialogSmooth::changeEvent(QEvent *e) { QDialog::changeEvent(e); switch (e->type()) { case QEvent::LanguageChange: ui->retranslateUi(this); break; default: break; } } void DialogSmooth::onTimer() { //Draw a new smooth image QImage image = ui->label->pixmap()->toImage(); const int maxy = image.height(); const int maxx = image.width(); for (int y=0; y!=maxy; ++y) { for (int x=0; x!=maxx; ++x) { image.setPixel(QPoint(x,y), QColor(std::rand() % 255, std::rand() % 255, std::rand() % 255).rgb()); } } ui->label->setPixmap(ui->label->pixmap()->fromImage(image)); }