QPainter::drawRects: Painter not active "错误 C++/QT

5

我是Qt和C++的初学者,想了解如何在Qt中使用QPainter和事件,但因执行时出现错误消息而卡住了,这是我的原始代码:

主.cpp

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

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
    QScopedPointer<QWidget> widget(new customWidget());
    widget->resize(240, 120);
    widget->show();

    return a.exec();
}

并且还有标题:

#ifndef CUSTOMWIDGET_H
#define CUSTOMWIDGET_H

#include <QWidget>
#include <QMouseEvent>
#include <QPoint>
#include <QPainter>

class customWidget : public QWidget
{
    Q_OBJECT
public:
    explicit customWidget(QWidget *parent = 0);
    void paintEvent(QPaintEvent *);
    void mouseMoveEvent(QMouseEvent *event);
    void mousePressEvent(QMouseEvent *event);

private:
    QPoint m_mousePos;
    QRect m_r2;
signals:

    void needToRepaint();
public slots:
};

#endif // CUSTOMWIDGET_H

还有 .cpp 文件:

#include "customwidget.h"

customWidget::customWidget(QWidget *parent) : QWidget(parent)
{
    QRect m_r2;
    QPoint m_mousePos;

    QObject::connect(this, SIGNAL(needToRepaint()), this, SLOT(repaint()));
}

void customWidget::paintEvent(QPaintEvent *)
{
    QPainter painter(this);

// ############ First Rectangle ****************************************

    QRect r1 = rect().adjusted(10, 10, -10, -10);
    painter.setPen(QColor("#FFFFFF"));
    painter.drawRect(r1);

// ############ Seconde Rectangle ****************************************

    QRect r2(QPoint(0, 0), QSize(100, 100));


    m_r2.moveCenter(m_mousePos);

    QPainter painter2;
    QPen pen;
    painter2.setPen(QColor("#000000"));
    pen.setWidth(3);
    painter2.setPen(pen);
    painter2.drawRect(m_r2);
    update();



}

void customWidget::mouseMoveEvent(QMouseEvent *event)
{

    m_mousePos = event->pos();

    emit needToRepaint();
}

我试图在网络上搜索,发现这是因为QPainter不在paintEvent中而无法正常工作,但在我的代码中不是这种情况,感谢你的帮助。


你需要调用 painter2.begin(objectWhereToDraw)painter2.end()。或者直接创建 QPainter painter2(objectWhereToDraw) - ilotXXI
2个回答

4
  1. 您只需要一个画家。第二个画家没有被激活,而且您也不需要它。

  2. 除非您确实需要在repaint()返回之前完成绘制(这就是发生的情况!),否则永远不要调用repaint()。如果您正确运行事件循环,您将永远不需要它。

  3. 不要从paintEvent()中调用update():这是无意义的(真的)。

  4. 当您希望重新绘制小部件时,请调用update():它会安排从事件循环进行更新。多个未完成的更新会合并以保持事件循环的功能,并防止事件风暴。

  5. 让编译器为您生成更多的内存管理代码。您已经通过使用智能指针完成了第一步 - 这很好。现在做第二步:通过值保存CustomWidget的实例。它不必显式动态分配。C++不是C,您可以利用值。

  6. 在简单的测试案例中,您不需要三个文件。您的代码应该尽可能少地占用行数,在单个main.cpp中完成。如果由于Q_OBJECT宏而需要moc文件,请在末尾添加#include "main.moc",并重新运行qmake来注意它。

修复问题后,测试案例应该如此。请记住:这是一个测试案例,不是100kLOC项目。您既不需要也不想要分散在三个文件中的可怜的35行代码。此外,通过分散代码,您使自己更难理解。

即使在大型项目中,除非您可以显示在相反的情况下获得显着的构建时间改进,否则您可以有许多完全在头文件中实现Java风格的小类。那是C++中唯一属于Java样式的东西。

// https://github.com/KubaO/stackoverflown/tree/master/questions/simple-paint-38796140
#include <QtWidgets>

class CustomWidget : public QWidget
{
   QPoint m_mousePos;
public:
   explicit CustomWidget(QWidget *parent = nullptr) : QWidget{parent} {}
   void paintEvent(QPaintEvent *) override;
   void mouseMoveEvent(QMouseEvent *event) override {
      m_mousePos = event->pos();
      update();
   }
};

void CustomWidget::paintEvent(QPaintEvent *)
{
   QPainter painter(this);

   auto r1 = rect().adjusted(10, 10, -10, -10);
   painter.setPen(Qt::white);
   painter.drawRect(r1);

   auto r2 = QRect{QPoint(0, 0), QSize(100, 100)};
   r2.moveCenter(m_mousePos);
   painter.setPen(QPen{Qt::black, 3, Qt::SolidLine, Qt::SquareCap, Qt::MiterJoin});
   painter.drawRect(r2);
}

int main(int argc, char ** argv) {
   QApplication app{argc, argv};
   CustomWidget w;
   w.show();
   return app.exec();
}

非常感谢您的答复和建议。我会立刻尝试 :D。 - N.D.

1

当用于创建 QPainter(QPixmap)QPixmap 无效时(如果该路径下没有文件),也可能会发生此错误。

在绘制之前,请确保您的 QPixmap 是正确的。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接