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

583 篇文章 127 订阅
196 篇文章 13 订阅

目录

 

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帧。

评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

IT1995

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值