5

I'm a beginner at Qt and c++ and I wanted to see how to use a QPainter and events in Qt but I got stuck because of an error message during the execution, my original code:

the main.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();
}

and the header:

#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

and the .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();
}

I tried to search it on the web and saw that it's because the QPainter isn't located in the paintEvent but it's not the case in my code, thanks for your help.

4

1 回答 1

4
  1. 你只需要一名画家。第二个没有激活,你也不需要它。

  2. repaint()除非您绝对需要在返回之前完成绘画,否则永远不要打电话repaint()(这就是发生的事情!)。如果您保持事件循环正常运行,您将永远不需要它。

  3. 不要打电话update()paintEvent()这是胡说八道(字面意思)。

  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();
}
于 2016-08-05T22:52:51.953 回答