QT OpenGL (1)2D Painting Example

2023-10-28 06:52
文章标签 qt opengl 2d example painting

本文主要是介绍QT OpenGL (1)2D Painting Example,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

2D Painting Example

为方便查阅,此文是原网站文档翻译与整理,如有侵权,请与本人联系。
官网


目录

  • 2D Painting Example
  • 概述
  • Helper类定义
  • Helper类实现
  • Widget类定义
  • Widget类实现
  • GLWidget类定义
  • GLWidget类实现
  • Window 类定义
  • Window 类实现
  • 运行示例


2D Painting示例展示了QPainter和QOpenGLWidget如何一起使用,以在支持的硬件上显示加速的2D图形。

在这里插入图片描述

QPainter类用于在QPaintDevice子类(如QWidget和QImage)提供的绘制设备上绘制2D图形基元。
由于QOpenGLWidget是QWidget的子类,因此可以重新实现其paintEvent()并使用QPainter在设备上绘制,就像使用QWidget一样。唯一的区别是,如果系统的OpenGL驱动程序支持,绘制操作将在硬件中加速。
在本例中,我们对QWidget和QOpenGLWidget执行相同的绘制操作。QWidget显示为启用了抗锯齿,如果系统的OpenGL驱动程序支持所需的扩展,QOpenGLWidget也将使用抗锯齿。

概述

为了能够将在QOpenGLWidget子类上绘制的结果与在QWidget子类中的本地绘制进行比较,我们希望并排显示这两种小部件。为此,我们派生了QWidget和QOpenGLWidget的子类,使用一个单独的Helper类为每个子类执行相同的绘制操作,并将它们放在一个顶级小部件中,该小部件本身提供了一个Window类。

Helper类定义

在本例中,绘制操作由辅助类执行。我们这样做是因为我们希望对QWidget子类和QOpenGLWidget子类执行相同的绘制操作。
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;
};

除了构造函数之外,它只提供了一个paint()函数来使用我们的一个小部件子类提供的painter进行绘制。

Helper类实现

类的构造函数设置将内容绘制到小部件上所需的资源:

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()函数中执行的。这需要一个已经设置为在绘制设备(QWidget或QOpenGLWidget)上绘制的QPainter,一个提供要绘制区域信息的QPaintEvent,以及自上次更新绘制设备以来经过的时间(以毫秒为单位)

void Helper::paint(QPainter *painter, QPaintEvent *event, int elapsed)
{painter->fillRect(event->rect(), background);painter->translate(100, 100);
/*
*在平移坐标系的原点之前,我们通过填充绘制事件中包含的区域来开始绘制,以便将其余的绘制操作移向绘制设备的中心。
*我们绘制了一个圆形的螺旋图案,使用指定的运行时间为它们设置动画,使它们看起来向外移动并围绕坐标系的原点移动:
*/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() QPainter的状态,然后restore()。
*/painter->setPen(textPen);painter->setFont(textFont);painter->drawText(QRect(-50, -50, 100, 100), Qt::AlignCenter, QStringLiteral("Qt"));
/*
*我们在原点绘制一些文本来完成效果。
*/

Widget类定义

Widget类提供了一个基本的自定义小部件,用于显示Helper类绘制的简单动画

class Helper;class Widget : public QWidget
{Q_OBJECTpublic:Widget(Helper *helper, QWidget *parent);public slots:void animate();protected:void paintEvent(QPaintEvent *event) override;private:Helper *helper;int elapsed;
};

除了构造函数之外,它只包含一个paintEvent()函数,该函数允许我们绘制自定义内容,以及一个用于为其内容设置动画的槽。一个成员变量跟踪小部件用来绘制其内容的Helper,另一个记录自上次更新以来所用的时间。

Widget类实现

构造函数只初始化成员变量,存储提供的Helper对象并调用基类的构造函数,并强制小部件的固定大小:

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

在这里,我们确定自计时器上次超时以来所经过的时间间隔,并在重新绘制小部件之前将其添加到任何现有值中。由于Helper类中使用的动画每秒循环一次,因此我们可以使用模运算符来确保经过的变量始终小于1000。
由于Helper类完成了所有实际绘制,我们只需要实现一个绘制事件,该事件为小部件设置一个QPainter并调用Helper的paint()函数:

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

GLWidget类定义

GLWidget类的定义与Widget类基本相同,只是它是从QOpenGLWidget派生的。

class Helper;class GLWidget : public QOpenGLWidget
{Q_OBJECTpublic:GLWidget(Helper *helper, QWidget *parent);public slots:void animate();protected:void paintEvent(QPaintEvent *event) override;private:Helper *helper;int elapsed;
};

同样,成员变量记录用于绘制小部件的Helper以及自上次更新以来经过的时间。

GLWidget类实现

构造函数与Widget类的构造函数略有不同:

GLWidget::GLWidget(Helper *helper, QWidget *parent): QOpenGLWidget(parent), helper(helper)
{elapsed = 0;setFixedSize(200, 200);setAutoFillBackground(false);// 多了这个设置
}

除了初始化逝去的成员变量和存储用于绘制widget的Helper对象外,还使用指定QGL::SampleBuffers标志的格式调用基类的构造函数。如果系统的OpenGL驱动程序支持,则可以启用抗锯齿功能。
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();
}

由于如果可用,将启用抗锯齿,我们只需要在小部件上设置一个QPainter,并调用助手的paint()函数来显示小部件的内容。

Window 类定义

Window类有一个基本的、最小的定义:

class Window : public QWidget
{Q_OBJECTpublic:Window();private:Helper helper;
};

它包含一个将在所有widgets之间共享的Helper对象。

Window 类实现

构造函数完成所有的工作,创建每种类型的widget ,并将它们与标签一起插入到布局中:

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毫秒的计时器是为动画目的而构建的,并连接到Widget和GLWidget对象的animate()插槽。一旦启动,小部件应该以每秒20帧左右的速度更新。

运行示例

该示例显示了在Widget和GLWidget中同时执行的相同绘制操作。GLWidget中渲染的质量和速度取决于系统的OpenGL驱动程序对多采样和硬件加速的支持程度。如果缺乏对其中任何一个的支持,驱动程序可能会依赖于软件渲染器,该软件渲染器可能会以质量换取速度。

这篇关于QT OpenGL (1)2D Painting Example的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/291474

相关文章

嵌入式QT开发:构建高效智能的嵌入式系统

摘要: 本文深入探讨了嵌入式 QT 相关的各个方面。从 QT 框架的基础架构和核心概念出发,详细阐述了其在嵌入式环境中的优势与特点。文中分析了嵌入式 QT 的开发环境搭建过程,包括交叉编译工具链的配置等关键步骤。进一步探讨了嵌入式 QT 的界面设计与开发,涵盖了从基本控件的使用到复杂界面布局的构建。同时也深入研究了信号与槽机制在嵌入式系统中的应用,以及嵌入式 QT 与硬件设备的交互,包括输入输出设

【QT】基础入门学习

文章目录 浅析Qt应用程序的主函数使用qDebug()函数常用快捷键Qt 编码风格信号槽连接模型实现方案 信号和槽的工作机制Qt对象树机制 浅析Qt应用程序的主函数 #include "mywindow.h"#include <QApplication>// 程序的入口int main(int argc, char *argv[]){// argc是命令行参数个数,argv是

Python QT实现A-star寻路算法

目录 1、界面使用方法 2、注意事项 3、补充说明 用Qt5搭建一个图形化测试寻路算法的测试环境。 1、界面使用方法 设定起点: 鼠标左键双击,设定红色的起点。左键双击设定起点,用红色标记。 设定终点: 鼠标右键双击,设定蓝色的终点。右键双击设定终点,用蓝色标记。 设置障碍点: 鼠标左键或者右键按着不放,拖动可以设置黑色的障碍点。按住左键或右键并拖动,设置一系列黑色障碍点

使用Qt编程QtNetwork无法使用

使用 VS 构建 Qt 项目时 QtNetwork 无法使用的问题 - 摘叶飞镖 - 博客园 (cnblogs.com) 另外,强烈建议在使用QNetworkAccessManager之前看看这篇文章: Qt 之 QNetworkAccessManager踏坑记录-CSDN博客 C++ Qt开发:QNetworkAccessManager网络接口组件 阅读目录 1.1 通用API函数

Qt多语种开发教程

Qt作为跨平台的开发工具,早已应用到各行各业的软件开发中。 今天讲讲,Qt开发的正序怎么做多语言开发。就是说,你设置中文,就中文显示;设置英语就英文显示,设置繁体就繁体显示,设置发育就显示法语等。 开发环境(其实多语种这块根环境没太大关系):win10,Qt.5.12.10 一.先用QtCreator创建一个简单的桌面程序 1.工程就随便命名“LanguageTest”,其他默认。 2.在设计师

Qt中window frame的影响

window frame 在创建图形化界面的时候,会创建窗口主体,上面会多出一条,周围多次一圈细边,这就叫window frame窗口框架,这是操作系统自带的。 这个对geometry的一些属性有一定影响,主要体现在Qt坐标系体系: 窗口当中包含一个按钮,这个按钮的坐标系是以父元素为参考,那么这个参考是widget本体作为参考,还是window frame作为参考,这两种参考体系都存在

【Qt】定时器事件

定时器事件 在之前学习QTimer中实现了定时器的功能,而在QTimer背后是QTimerEvent定时器事件进行支撑的。在QObject中提供了一个timeEvent这个函数。 startTimer启动定时器killTimer关闭定时器 Qt 中在进⾏窗⼝程序的处理过程中,经常要周期性的执⾏某些操作,或者制作⼀些动画效果,使⽤定 时器就可以实现。所谓定时器就是在间隔⼀定时间后,去执⾏某⼀

QT 编译报错:C3861: ‘tr‘ identifier not found

问题: QT 编译报错:C3861: ‘tr’ identifier not found 原因 使用tr的地方所在的类没有继承自 QObject 类 或者在不在某一类中, 解决方案 就直接用类名引用 :QObject::tr( )

Matter.js:Web开发者的2D物理引擎

Matter.js:Web开发者的2D物理引擎 前言 在现代网页开发中,交互性和动态效果是提升用户体验的关键因素。 Matter.js,一个专为网页设计的2D物理引擎,为开发者提供了一种简单而强大的方式,来实现复杂的物理交互效果。 无论是模拟重力、碰撞还是复杂的物体运动,Matter.js 都能轻松应对。 本文将带你深入了解 Matter.js ,并提供实际的代码示例,让你一窥其强大功能

OPENGL顶点数组, glDrawArrays,glDrawElements

顶点数组, glDrawArrays,glDrawElements  前两天接触OpenGL ES的时候发现里面没有了熟悉的glBegin(), glEnd(),glVertex3f()函数,取而代之的是glDrawArrays()。有问题问google,终于找到答案:因为OpenGL ES是针对嵌入式设备这些对性能要求比较高的平台,因此把很多影响性能的函数都去掉了,上述的几个函数都被移除了。接