Qt文档阅读笔记-官方2D Painting Example实例解析

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/qq78442761/article/details/87626838

目录

2D Painting Example

Overview

Helper Class Definition

Helper Class Implementation

Widget Class Definition

Widget Class Implementation

GLWidget Class Definition

GLWidget Class Implementation

Window Class Definition

Window Class Implementation


2D Painting Example

QPainter类将2D的绘图给QpaintDevice的子类,这个子类包括QWidget和QImage。
QGLWidget是QWidget的子类,所以他可以重写paintEvent或Qpainter在设备上画图。但是这个painteEvent和QPainter和普通的QWidget是不同的,如果本机的OpenGL支持绘图,那么将会得到硬件的加速支持。
本例中,QWidget和QGLWidget的绘图,并且QWidget还抗锯齿,QGLWidget如果硬件支持,也能抗锯齿。

Overview

这里使用了QGLWidget和QWidget描绘的界面进行对比,并且,这个对比很直观,就放在旁边,这里使用Helper类去画相同的画面。

Helper Class Definition

在这个例子,为了描绘相同的动画效果,用了Helper类去画相同的功能。
Helper类:

  class Helper
  {
  public:
      Helper();

  public:
      void paint(QPainter *painter, QPaintEvent *event, int elapsed);

  private:
      QBrush background;
      QBrush circleBrush;
      QFont textFont;
      QPen circlePen;
      QPen textPen;
  };

除了构造函数,helper类还提供了painter函数去画东西。

Helper Class Implementation

构造函数的作用是初始化各个变量。

  Helper::Helper()
  {
      QLinearGradient gradient(QPointF(50, -20), QPointF(80, 20));
      gradient.setColorAt(0.0, Qt::white);
      gradient.setColorAt(1.0, QColor(0xa6, 0xce, 0x39));

      background = QBrush(QColor(64, 32, 64));
      circleBrush = QBrush(gradient);
      circlePen = QPen(Qt::black);
      circlePen.setWidth(1);
      textPen = QPen(Qt::white);
      textFont.setPixelSize(50);
  }

绘制在paint()函数中使用QPainter类去在设备上画图。QPaintEvent提供了绘制区域的问题。

  void Helper::paint(QPainter *painter, QPaintEvent *event, int elapsed)
  {
      painter->fillRect(event->rect(), background);
      painter->translate(100, 100);

在转换坐标前,首先填充下painter的区域,这样其余的画图都会从被转换坐标开始。
画一个螺旋,指定时间做指定的动作,让看的人感觉它是向外旋转。

      painter->save();
      painter->setBrush(circleBrush);
      painter->setPen(circlePen);
      painter->rotate(elapsed * 0.030);

      qreal r = elapsed / 1000.0;
      int n = 30;
      for (int i = 0; i < n; ++i) {
          painter->rotate(30);
          qreal factor = (i + r) / n;
          qreal radius = 0 + 120.0 * factor;
          qreal circleRadius = 1 + factor * 20;
          painter->drawEllipse(QRectF(radius, -circleRadius,
                                      circleRadius * 2, circleRadius * 2));
      }
      painter->restore();

在这个坐标系统中旋转了很多次,所以调用save()在让其复原,调用restore()。

      painter->setPen(textPen);
      painter->setFont(textFont);
      painter->drawText(QRect(-50, -50, 100, 100), Qt::AlignCenter, QStringLiteral("Qt"));
  }

Widget Class Definition

Widget使用helper类去绘画

  class Helper;

  class Widget : public QWidget
  {
      Q_OBJECT

  public:
      Widget(Helper *helper, QWidget *parent);

  public slots:
      void animate();

  protected:
      void paintEvent(QPaintEvent *event) override;

  private:
      Helper *helper;
      int elapsed;
  };

除了构造函数,还有paintEvent()函数,elapsed用于记录上次更新时间。

Widget Class Implementation

构造函数初始化各个成员。

  Widget::Widget(Helper *helper, QWidget *parent)
      : QWidget(parent), helper(helper)
  {
      elapsed = 0;
      setFixedSize(200, 200);
  }

animate()槽函数在任一时间被调用。

  void Widget::animate()
  {
      elapsed = (elapsed + qobject_cast<QTimer*>(sender())->interval()) % 1000;
      update();
  }

在paintEvent()中调用Helper类实现重绘。

  void Widget::paintEvent(QPaintEvent *event)
  {
      QPainter painter;
      painter.begin(this);
      painter.setRenderHint(QPainter::Antialiasing);
      helper->paint(&painter, event, elapsed);
      painter.end();
  }

GLWidget Class Definition

GLWidget用于展示OpenGL绘图界面。

  class Helper;

  class GLWidget : public QOpenGLWidget
  {
      Q_OBJECT

  public:
      GLWidget(Helper *helper, QWidget *parent);

  public slots:
      void animate();

  protected:
      void paintEvent(QPaintEvent *event) override;

  private:
      Helper *helper;
      int elapsed;
  };

Helper类绘图,elapsed记录上一次更新的时间。

GLWidget Class Implementation

构造函数与Widget的构造函数是有差异的。

  GLWidget::GLWidget(Helper *helper, QWidget *parent)
      : QOpenGLWidget(parent), helper(helper)
  {
      elapsed = 0;
      setFixedSize(200, 200);
      setAutoFillBackground(false);
  }

QGL::SampleBuffers这个标识可以设置OpenGL抗锯齿,如果系统没有OpenGLDriver话是开启不成功的。可以设置OpenGL抗锯齿,如果系统没有OpenGLDriver话是开启不成功的。
animate()和widget一样。

  void GLWidget::animate()
  {
      elapsed = (elapsed + qobject_cast<QTimer*>(sender())->interval()) % 1000;
      update();
  }

paintEvent()和widget一样。

  void GLWidget::paintEvent(QPaintEvent *event)
  {
      QPainter painter;
      painter.begin(this);
      painter.setRenderHint(QPainter::Antialiasing);
      helper->paint(&painter, event, elapsed);
      painter.end();
  }

Window Class Definition

window类:

  class Window : public QWidget
  {
      Q_OBJECT

  public:
      Window();

  private:
      Helper helper;
  };

包含一个Helper用于传给上面的两个界面。

Window Class Implementation

构造函数初始化,构造界面,以及布局:

  Window::Window()
  {
      setWindowTitle(tr("2D Painting on Native and OpenGL Widgets"));

      Widget *native = new Widget(&helper, this);
      GLWidget *openGL = new GLWidget(&helper, this);
      QLabel *nativeLabel = new QLabel(tr("Native"));
      nativeLabel->setAlignment(Qt::AlignHCenter);
      QLabel *openGLLabel = new QLabel(tr("OpenGL"));
      openGLLabel->setAlignment(Qt::AlignHCenter);

      QGridLayout *layout = new QGridLayout;
      layout->addWidget(native, 0, 0);
      layout->addWidget(openGL, 0, 1);
      layout->addWidget(nativeLabel, 1, 0);
      layout->addWidget(openGLLabel, 1, 1);
      setLayout(layout);

      QTimer *timer = new QTimer(this);
      connect(timer, &QTimer::timeout, native, &Widget::animate);
      connect(timer, &QTimer::timeout, openGL, &GLWidget::animate);
      timer->start(50);
  }

每50毫秒重绘一下,大约每秒20帧。

猜你喜欢

转载自blog.csdn.net/qq78442761/article/details/87626838