Unable to paint on Qt Widget, shows error “paintEngine: Should no longer be called”
-
You are calling
drawFirstPoint
anddrawSecondPoint
from withinmousePressEvent
. Don't do that. The only place you should create and use a painter is insidepaintEvent
. Instead of drawing from mouse event store the data to draw (the position and which button was pressed) and callupdate()
. This will schedule a paint event, inside of which you can check the data and paint what's needed.Btw:
void paintEvent(QPaintEvent *event); void mousePressEvent(QMouseEvent *event) Q_DECL_OVERRIDE;
Be consistent. If you use Q_DECL_OVERRIDE on one override (good!), use it on all of them.
-
@Chris-Kawa Thanks for the suggestion, i am inspired from the qt example
scribble
in doing my program, in that example the painter is created and used indrawLineTo
and updated. Do you know how that works?I also tried to modify my program accordingly as you said but its getting complicated for me, maybe i am doing mistakes.
One more question, what is the difference in these two below errors?
QPainter::begin: Paint device returned engine == 0, type: 3
and
QPainter::begin: Paint device returned engine == 0, type: 1
-
hi
The Scribble example draws to a imagevoid ScribbleArea::drawLineTo(const QPoint &endPoint)
{
QPainter painter(&image); << to image
...
}and then it paints that image in paint
void ScribbleArea::paintEvent(QPaintEvent *event)
{
QPainter painter(this);
QRect dirtyRect = event->rect();
painter.drawImage(dirtyRect, image, dirtyRect); << draw image
}To avoid drawing whole picture each time, it uses the event->rect();
that tells which area need repainting.
This are is set by drawLineTo. -
@mrjj thanks for your kind reply, I understood what you explained and wanted to try the scribble example. I made a test program to check the scribble example by using Qt Widget creator. I made widget using
ui class
and the inside code is completely fromscribble
example but modified. This time i am getting the error asQPainter::begin: Paint device returned engine == 0, type: 3
Can you please find the problem. This is my code
mainwindow.h
#ifndef MAINWINDOW_H #define MAINWINDOW_H #include <QMainWindow> #include "inputwindow.h" #include "outputwindow.h" #include <QFileDialog> #include <QInputDialog> #include <QColorDialog> #include <QtGui> #include <QtCore> #include <QPoint> #include <QImage> namespace Ui { class MainWindow; class Inputwindow; } class MainWindow : public QMainWindow { Q_OBJECT public: explicit MainWindow(QWidget *parent = 0); ~MainWindow(); QImage image; QColor penColor() const { return newPenColor; } int penWidth() const { return newPenWidth; } public slots: private slots: void on_open_clicked(); void on_penwidth_clicked(); void on_pencolor_clicked(); private: Ui::MainWindow *ui; Inputwindow *inputwindow; int newPenWidth; QColor newPenColor; }; #endif // MAINWINDOW_H
inputwindow.h
#ifndef INPUTWINDOW_H #define INPUTWINDOW_H #include <QWidget> #include <QHBoxLayout> namespace Ui { class Inputwindow; } class Inputwindow : public QWidget { Q_OBJECT public: explicit Inputwindow(QWidget *parent = 0); ~Inputwindow(); QImage image; bool open(const QString &fileName); bool isModified() const { return modified; } QColor penColor() const { return newPenColor; } int penWidth() const { return newPenWidth; } protected: void mousePressEvent(QMouseEvent *event) Q_DECL_OVERRIDE; void mouseMoveEvent(QMouseEvent *event) Q_DECL_OVERRIDE; void mouseReleaseEvent(QMouseEvent *event) Q_DECL_OVERRIDE; void paintEvent(QPaintEvent *event) Q_DECL_OVERRIDE; private slots: private: Ui::Inputwindow *ui; bool modified; bool scribbling; QPoint lastPoint; int newPenWidth; QColor newPenColor; void drawLineTo(const QPoint &endPoint); }; #endif // INPUTWINDOW_H
mainwindow.cpp
#include "mainwindow.h" #include "ui_mainwindow.h" #include "inputwindow.h" MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent), ui(new Ui::MainWindow) { ui->setupUi(this); //setCentralWidget(inputwindow); } MainWindow::~MainWindow() { delete ui; } void MainWindow::on_open_clicked() { QString fileName = QFileDialog::getOpenFileName(this, tr("choose"), "", tr("Image(*.png *.jpg *.jpeg *.bmp *.gif)")); if (QString::compare(fileName, QString())!=0) { inputwindow = new Inputwindow(this); inputwindow->setGeometry(QRect(QPoint(10,50),QSize(690,400))); inputwindow->open(fileName); inputwindow->show(); } } void MainWindow::on_penwidth_clicked() { bool ok; int newWidth = QInputDialog::getInt(this, tr("Scribble"), tr("Select pen width:"), this->penWidth(), 1, 50, 1, &ok); if (ok) newPenWidth = newWidth; } void MainWindow::on_pencolor_clicked() { QColor newColor = QColorDialog::getColor(this->penColor()); if (newColor.isValid()) newPenColor = newColor; }
inputwindow.cpp
#include "inputwindow.h" #include "ui_inputwindow.h" #include <QtWidgets> Inputwindow::Inputwindow(QWidget *parent) : QWidget(parent), ui(new Ui::Inputwindow) { ui->setupUi(this); setAttribute(Qt::WA_StaticContents); modified = false; scribbling = false; newPenWidth = 1; newPenColor = Qt::blue; } Inputwindow::~Inputwindow() { delete ui; } bool Inputwindow::open(const QString &fileName) { QImage image; bool valid = image.load(fileName); if (valid) { image = image.scaledToWidth(ui->label->width(), Qt::SmoothTransformation); ui->label->setPixmap(QPixmap::fromImage(image)); update(); return true; } else { //Error handling } } void Inputwindow::paintEvent(QPaintEvent *event) { QPainter painter(this); QRect dirtyRect = event->rect(); painter.drawImage(dirtyRect, image, dirtyRect); } void Inputwindow::mousePressEvent(QMouseEvent *event) { scribbling = true; if (event->button() == Qt::LeftButton) { lastPoint = event->pos(); scribbling = true; } } void Inputwindow::mouseMoveEvent(QMouseEvent *event) { if ((event->buttons() & Qt::LeftButton) && scribbling) drawLineTo(event->pos()); } void Inputwindow::mouseReleaseEvent(QMouseEvent *event) { if (event->button() == Qt::LeftButton && scribbling) { drawLineTo(event->pos()); scribbling = false; } } void Inputwindow::drawLineTo(const QPoint &endPoint) { QPainter painter(&image); painter.setPen(QPen(newPenColor, newPenWidth, Qt::SolidLine, Qt::RoundCap, Qt::RoundJoin)); painter.drawLine(lastPoint, endPoint); modified = true; int rad = (newPenWidth / 2) + 2; update(QRect(lastPoint, endPoint).normalized() .adjusted(-rad, -rad, +rad, +rad)); lastPoint = endPoint; }
-
@beginMyCoding said:
drawLineTo
There you use image variable.
Where is image created/set a size for the image.
This error could be due to image having no size.
Im not sure its the case, but easy to test
could you try qDebug() <<"img:" << image.isNull() ; -
@beginMyCoding
Im still not 100% sure u set the imageyou have defined in
class Inputwindow : public QWidget
{
public:
QImage image; <<<< -- this one is used in Inputwindow::drawLineTo
xxxand you do in Inputwindow::open
ui->label->setPixmap(QPixmap::fromImage(image));
but this "image" is local variable.
so that is a Label having the image and the "other image " frm .h is not used. ?or does the massive scrolling confuse my brain ?
--
qDebug() <<"img:" << image.isNull() ;
in paintevent -
@mrjj said:
qDebug() <<"img:" << image.isNull() ;
This is what i am getting when i use
qDebug() <<"img:" << image.isNull() ;
in paintEvent
img: true img: true img: true img: true img: true img: true img: true img: true QPainter::begin: Paint device returned engine == 0, type: 3 QPainter::setPen: Painter not active img: true img: true img: true
-
As @mrjj already said you load your image into a local variable in open():
bool Inputwindow::open(const QString &fileName) { QImage image; <-- this one is not the one you use later! bool valid = image.load(fileName); if (valid) { image = image.scaledToWidth(ui->label->width(), Qt::SmoothTransformation); ui->label->setPixmap(QPixmap::fromImage(image)); update(); return true; } else { //Error handling } }
That means your QImage image in InputWindow is not set! Remove this line in open():
QImage image;
-
@jsulm Hi
Thanks for you reply..
I removed the lineQImage image
as you mentioned. I got rid of the errors but its not painting if i try to paint on the Image. I wanted to paint on the image loaded in inputwindow.
Do you know what mistake i am making? -
Hi
Maybe the label is covering up the image.ui->label->setPixmap(QPixmap::fromImage(image));
This shows a copy of the image on screen. (not the one u draw on)
Try to remove it and see if that makes difference.