实战PyQt5: 088-QOpenGLWidget部件

QOpenGLWidget简介

QOpenGLWidget类是用于渲染OpenGL图形的部件。QOpenGLWidget提供了用于显示集成到Qt应用程序中的OpenGL图形的功能。使用非常简单:让应用的类继承自它,并像使用其他任何QWidget一样使用子类,而且它可以在使用QPainter和标准OpenGL渲染命令之间进行选择。

QOpenGLWidget提供了三个函数,在子类中重新实现它们就可以执行一个典型的OpenGL任务:

  • paintGL() 渲染OpenGL场景。在部件需要更新时就会调用它。
  • resizeGL() 设置OpenGL视口,投影等。只要调整了窗口部件的大小(以及新创建的窗口部件自动获得resize事件而首次显示时),就会被调用。
  • initializeGL() 设置OpenGL资源和状态。在第一次调用resizeGL()或paintGL()之前它被调用一次。

QOpenGLWidget的子类可以通过以下方式渲染纯3D内容:

  • 重新实现initializeGL()和resizeGL()函数以设置OpenGL状态并提供透视图转换。
  • 重新实现paintGL()来绘制3D场景,它仅调用OpenGL函数。

仅使用QPainter执行绘图时,还可以像执行普通部件一样执行绘图:

  • 重新实现paintEven()t函数。
  • 构造一个以部件为目标的QPainter对象。将小部件传递给构造函数或QPainter.begin()函数。
  • 使用QPainter的成员函数绘制基本图元。
  • 绘制完成后,然后销毁QPainter实例。或者显式调用QPainter.end()。

QOpenGLWidget常用方法:

  • context(): 返回控件所使用的QOpenGLContext, 如果未初始化,则返回None。
  • defaultFramebufferObject():返回帧缓冲区句柄,如果未初始化,则返回None。
  • doneCurrent(): 释放Context。
  • format(): 返回本控件及其顶层窗口使用的Context和Surface格式。
  • grabFramebuffer(): 渲染并返回帧缓冲区的32位RGB图像。
  • makeCurrent(): 通过使相应的context成为当前context并在其上绑定framebuffer对象,为渲染此控件的OpenGL内容做准备。
  • setFormat(): 设置所需的表面(Surface)格式。
  • setTextureFormat(): 设置自定义内部纹理格式。
  • textureFormat(): 返回内部纹理格式。

QOpenGLWidget常用信号:

  • aboutToCompose(): 当控件的顶级窗口开始合成其QOpenGLWidget子级和其他控件的纹理时,将发出此信号。
  • aboutToResize(): 当窗口部件的大小发生更改时,将发出此信号,因此将重新创建帧缓冲区对象。
  • frameSwapped(): 在窗口部件的顶级窗口完成合成后发出此信号。
  • resized(): 调整窗口部件的大小而重新创建了帧缓冲对象之后立即发出此信号。

QOpenGLWidget类继承关系:

实战PyQt5: 088-QOpenGLWidget部件

范例代码

最简单的QOpenGLWidget子类可能如下所示:

class MyGLWidget(QOpenGLWidget):
         def __init(self, parent=None):
                   super(MyGLWidget, self).__init__(parent)
        
         def initializeGL(self):
                   # 设置渲染context,加载shader和资源等
                   version_profile = QOpenGLVersionProfile()
                   version_profile.setVersion(2,0)
                   self.gl = self.context().versionFunctions(version_profile)
                   self.gl.initializeOpenGLFunctions()
                   ...
 
         def resizeGL(self, w, h):
                   # 更新投射矩阵和其他尺寸相关的设置
                   self.projection.setToIdentity()
                   self.projection.perspective(45, w / h, 0.01, 100)
                   ...
 
         def paintGL():
                   #绘制场景
                   self.gl.glClear(self.gl.GL_COLOR_BUFFER_BIT)

在演示代码中,使用OpenGL渲染了一个三个顶点带不同颜色的三角形,完整代码如下:

import sys
from PyQt5 import QtCore, QtGui, QtWidgets
from PyQt5.QtCore import Qt
from PyQt5.QtGui import QColor, QOpenGLVersionProfile
from PyQt5.QtWidgets import (QApplication, QWidget, QOpenGLWidget, QHBoxLayout)
 
class MyGLWidget(QOpenGLWidget):
    
    def __init__(self, parent=None):
        super(MyGLWidget, self).__init__(parent)
        
    def initializeGL(self):
        version_profile = QOpenGLVersionProfile()
        version_profile.setVersion(2, 0)
        self.gl = self.context().versionFunctions(version_profile)
        self.gl.initializeOpenGLFunctions()
        
        #设置背景色
        self.gl.glClearColor(0.2, 0.4, 0.52, 1.0)
        #深度测试
        self.gl.glEnable(self.gl.GL_DEPTH_TEST)
        
    def paintGL(self):
        self.gl.glClear(self.gl.GL_COLOR_BUFFER_BIT | self.gl.GL_DEPTH_BUFFER_BIT)
        self.gl.glLoadIdentity()
          
        #self.gl.glRotated(30.0, 1.0, 0.0, 0.0)       
        self.gl.glBegin(self.gl.GL_TRIANGLES)
        self.gl.glColor3d(1.0, 0.0, 0.0)
        self.gl.glVertex3d(0.0, 1.0, 0.0)
        self.gl.glColor3d(0.0, 1.0, 0.0)
        self.gl.glVertex3d(-1.0, -1.0, 0.0)
        self.gl.glColor3d(0.0, 0.0, 1.0)
        self.gl.glVertex3d(1.0, -1.0, 0.0)
        self.gl.glEnd()
        
    def resizeGL(self, width, height):
 
        side = min(width, height)
        if side < 0:
            return
            
        #视口
        self.gl.glViewport((width - side) // 2, (height - side) // 2, side, side)
        self.gl.glMatrixMode(self.gl.GL_PROJECTION)
        self.gl.glLoadIdentity()
        #正交投射
        self.gl.glOrtho(-1.5, 1.5, -1.5, 1.5, -10, 10)
        self.gl.glMatrixMode(self.gl.GL_MODELVIEW)
 
class DemoOpenGLWidget(QWidget):
    def __init__(self, parent=None):
        super(DemoOpenGLWidget, self).__init__(parent)   
        
        # 设置窗口标题
        self.setWindowTitle('实战PyQt5: QOpenGLWidget Demo!')      
        # 设置窗口大小
        self.resize(400, 320)
      
        self.initUi()
        
    def initUi(self):
        glWidget = MyGLWidget()
        
        mainLayout = QHBoxLayout()
        mainLayout.addWidget(glWidget)
        
        self.setLayout(mainLayout)
    
if __name__ == '__main__':
    app = QApplication(sys.argv)
    window = DemoOpenGLWidget()
    window.show()
    sys.exit(app.exec())  

运行结果如下图:

实战PyQt5: 088-QOpenGLWidget部件

测试QOpenGLWidget

本文知识点

  • 如何实现一个OpenGL渲染任务;
  • OpenGL的状态机制;
  • OpenGL 渲染一个三角形。

前一篇: 实战PyQt5: 087-视图类QGraphicsView

  • 7
    点赞
  • 37
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值