ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

实战PyQt5: 088-QOpenGLWidget部件

2020-12-04 13:01:40  阅读:5435  来源: 互联网

标签:088 1.0 OpenGL 0.0 self PyQt5 gl 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

标签:088,1.0,OpenGL,0.0,self,PyQt5,gl,QOpenGLWidget
来源: https://blog.csdn.net/seniorwizard/article/details/110633129

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有