简体   繁体   中英

Unable to paint on Qt Widget, shows error “paintEngine: Should no longer be called”

I have created a widget using Qt Creator such a way that it has two sub windows inside a main window and some push buttons to load, save images, set pen width and color to paint on the window. But when i start to paint it gives me error saying

 QWidget::paintEngine: Should no longer be called  
 QPainter::begin: Paint device returned engine == 0, type: 1  
 QPainter::setPen: Painter not active  
 QPainter::drawPoints: Painter not active

Does anyone know what mistake i am doing, i checked threads related to this topic but could not find suitable solution. I am also new to c++, so please help me to find a solution

This is my code below

widget.h

#ifndef WIDGET_H
#define WIDGET_H

#include <QWidget>
#include <QtCore>
#include <QImage>
#include <QColor>
#include <QPoint>
#include <QtGui>
#include <QPainter>
#include <QMainWindow>
#include <QFileDialog>

namespace Ui {
class Widget;
}

class Widget : public QWidget
{
    Q_OBJECT

public:
    explicit Widget(QWidget *parent = 0);
    ~Widget();

    bool isModified() const { return modified; }
    QColor penColor() const { return newPenColor; }
    int penWidth() const { return newPenWidth; }


protected:
    void paintEvent(QPaintEvent *event);
    void mousePressEvent(QMouseEvent *event) Q_DECL_OVERRIDE;

private slots:
    void on_open_clicked();

    void on_save_clicked();

    void on_penWidth_clicked();

    void on_penColor_clicked();

private:
    Ui::Widget *ui;

    QImage image;
    QPixmap imageobject;
    int newPenWidth;
    QColor newPenColor;
    bool modified;
    bool scribbling;
    QPoint firstPoint, secondPoint;
    void drawFirstPoint(const QPoint);
    void drawSecondPoint(const QPoint);
};

#endif // WIDGET_H

main.cpp

#include "widget.h"
#include <QApplication>

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
    Widget w;
    w.show();

    return a.exec();
}

widget.cpp

#include "widget.h"
#include "ui_widget.h"
#include <QtWidgets>
#ifndef QT_NO_PRINTER
#include <QtPrintSupport/QPrinter>
#include <QtPrintSupport/QPrintDialog>
#endif
#include <QLabel>
#include <QWidget>


Widget::Widget(QWidget *parent) : QWidget(parent),
    ui(new Ui::Widget)
{
    ui->setupUi(this);

    setAttribute(Qt::WA_StaticContents);
    modified = false;
    scribbling = false;
    newPenWidth = 1;
    newPenColor = Qt::blue;
}

Widget::~Widget()
{
    delete ui;
}

void Widget::on_open_clicked()
{
    QString filename = QFileDialog::getOpenFileName(this, tr("choose"), "", tr("Image(*.png *.jpg *.jpeg *.bmp *.gif)"));
       if (QString::compare(filename, QString())!=0)
       {
           QImage image;
           bool valid = image.load(filename);
           if (valid)
           {
               image = image.scaledToWidth(ui->inputWindow->width(), Qt::SmoothTransformation);
               ui->inputWindow->setPixmap(QPixmap::fromImage(image));

               image = image.scaledToWidth(ui->outputWindow->width(), Qt::SmoothTransformation);
               ui->outputWindow->setPixmap(QPixmap::fromImage(image));
           }
           else
           {
               //Error handling
           }
       }
}

void Widget::on_save_clicked()
{
    QString filename = QFileDialog::getSaveFileName(this,tr("choose"), "", tr("PNG (*.png);; JPEG (*.jpg *.jpeg);; BMP(*.bmp);; GIF(*.gif)"));

    QImage imageobject = image;
    imageobject.save(filename);

}

void Widget::paintEvent(QPaintEvent *event)
{
    QPainter painter(this);
    QRect dirtyRect = event->rect();
    painter.drawImage(dirtyRect, image, dirtyRect);
}

void Widget::mousePressEvent(QMouseEvent *event)
{
    scribbling = true;
    if (event->button() == Qt::LeftButton && scribbling)
    {
        firstPoint = event->pos();
        drawFirstPoint(firstPoint);
    }
    else if (event->button() == Qt::RightButton && scribbling) {
             secondPoint = event->pos();
             drawSecondPoint(secondPoint);

    }
}

void Widget::drawFirstPoint(const QPoint)
{
    QPainter painter(this);
    painter.setPen(QPen(newPenColor, newPenWidth, Qt::SolidLine, Qt::RoundCap,
                        Qt::RoundJoin));

    painter.drawPoint(firstPoint);
    modified = true;
    int rad = (newPenWidth / 2) + 2;
    update(QRect(firstPoint, firstPoint).normalized().adjusted(-rad, -rad, +rad, +rad));
}

void Widget::drawSecondPoint(const QPoint)
{
    QPainter painter(this);
    painter.setPen(QPen(newPenColor, newPenWidth, Qt::SolidLine, Qt::RoundCap,
                        Qt::RoundJoin));

    painter.drawPoint(secondPoint);
    modified = true;
    int rad = (newPenWidth / 2) + 2;
    update(QRect(secondPoint, secondPoint).normalized().adjusted(-rad, -rad, +rad, +rad));
}

void Widget::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 Widget::on_penColor_clicked()
{
    QColor newColor = QColorDialog::getColor(this->penColor());
    if (newColor.isValid())
        newPenColor = newColor;
}

widget.ui

<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
 <class>Widget</class>
 <widget class="QWidget" name="Widget">
  <property name="enabled">
   <bool>true</bool>
  </property>
  <property name="geometry">
   <rect>
    <x>0</x>
    <y>0</y>
    <width>1300</width>
    <height>700</height>
   </rect>
  </property>
  <property name="windowTitle">
   <string>Test window</string>
  </property>
  <property name="layoutDirection">
   <enum>Qt::LeftToRight</enum>
  </property>
  <widget class="QLabel" name="inputWindow">
   <property name="geometry">
    <rect>
     <x>40</x>
     <y>120</y>
     <width>600</width>
     <height>500</height>
    </rect>
   </property>
   <property name="maximumSize">
    <size>
     <width>600</width>
     <height>16777215</height>
    </size>
   </property>
   <property name="cursor">
    <cursorShape>CrossCursor</cursorShape>
   </property>
   <property name="text">
    <string>TextLabel</string>
   </property>
  </widget>
  <widget class="QLabel" name="outputWindow">
   <property name="geometry">
    <rect>
     <x>660</x>
     <y>120</y>
     <width>600</width>
     <height>500</height>
    </rect>
   </property>
   <property name="maximumSize">
    <size>
     <width>600</width>
     <height>16777215</height>
    </size>
   </property>
   <property name="text">
    <string>TextLabel</string>
   </property>
  </widget>
  <widget class="QWidget" name="layoutWidget">
   <property name="geometry">
    <rect>
     <x>170</x>
     <y>10</y>
     <width>651</width>
     <height>31</height>
    </rect>
   </property>
   <layout class="QHBoxLayout" name="horizontalLayout">
    <item>
     <widget class="QPushButton" name="open">
      <property name="cursor">
       <cursorShape>PointingHandCursor</cursorShape>
      </property>
      <property name="text">
       <string>OPEN</string>
      </property>
     </widget>
    </item>
    <item>
     <widget class="QPushButton" name="save">
      <property name="cursor">
       <cursorShape>PointingHandCursor</cursorShape>
      </property>
      <property name="text">
       <string>SAVE</string>
      </property>
     </widget>
    </item>
    <item>
     <widget class="QPushButton" name="penWidth">
      <property name="text">
       <string>Pen Width</string>
      </property>
     </widget>
    </item>
    <item>
     <widget class="QPushButton" name="penColor">
      <property name="text">
       <string>Pen Color</string>
      </property>
     </widget>
    </item>
    <item>
     <widget class="QPushButton" name="pushButton_5">
      <property name="text">
       <string>PushButton</string>
      </property>
     </widget>
    </item>
   </layout>
  </widget>
 </widget>
 <layoutdefault spacing="6" margin="11"/>
 <resources/>
 <connections/>
</ui>

All painting on a widget must happen in the paintEvent() function, and you are trying to paint outside of it - that won't work.

You must either find a way to put all your drawing calls inside the paintEvent() function, or draw on a buffer, for example a QPixmap and then draw that pixmap onto the widget in the paintEvent() When you draw on a buffer you can draw from everywhere, the limitation is only for widget drawing. For pixmaps you (usually) must draw from the main thread, if you want to draw from another thread, use QImage instead.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM