【问题标题】:Converting QWidget to QOpenGLWidget将 QWidget 转换为 QOpenGLWidget
【发布时间】:2017-08-10 05:06:04
【问题描述】:

我有一个 PyQt5 应用程序,它可以在我的开发机器上完美运行,但在我的目标嵌入式设备 (Raspberry Pi 2) 上存在严重的性能问题。我将我的应用程序从 PySide(基于 Qt4)移植到 PyQt5,以便在 RPi2 上使用基于 eglfs 的 Qt 构建,以期提高图形性能(直接写入具有硬件加速支持的帧缓冲区),但我尚未将基于光栅引擎的 QWidget(以及相关的 QPainter() 类)转换为硬件加速的等价物。

下面是我工作的基于 Qt4 的 QWidget() paintEvent 类的摘录,它在静态 .png 背景上绘制了一个动态量规指针:

class Qt4Widget(QtGui.QWidget):
    def __init__(self, parent=None):
        super(Qt4Widget, self).__init__(parent)
        self.Background = QtGui.QPixmap("Images/Background.png")

        #Other initialisation activity

    #The paintEvent is called from various Qt4Widget.update(self) calls
    def paintEvent(self, e):
        self.Painter = QtGui.QPainter(self)
        self.Painter.setRenderHint(self.Painter.Antialiasing)

        self.Rect = e.rect()
        self.MainRect = QtCore.QRect(self.Rect)
        self.MainSize = self.MainRect.size()
        self.MainPosition = self.MainRect.center()
        self.MainRect.moveCenter(QtCore.QPoint(self.MainPosition.x()-self.MainSize.width(), self.MainPosition.y()-self.MainSize.height()))

        self.MainRect.setSize(self.MainSize*0.85)
        self.MainRect.moveCenter(self.MainPosition)

        self.RefillRect = QtCore.QRect(self.MainRect)
        self.MainSize = self.RefillRect.size()
        self.MainPosition = self.RefillRect.center()
        self.RefillRect.moveCenter(QtCore.QPoint(self.MainPosition.x()-self.MainSize.width(), self.MainPosition.y()-self.MainSize.height()))

        self.RefillRect.setSize(self.MainSize*0.6)
        self.RefillRect.moveCenter(self.MainPosition)

        self.MainPainter.setPen(QtCore.Qt.NoPen)

        self.MainPainter.drawPixmap(self.Rect, self.Background)

        self.Painter.save()

        self.Gradient = QtGui.QConicalGradient(QtCore.QPointF(self.MainRect.center()), 273.0)
        self.Gradient.setColorAt(.8, QtCore.Qt.white)
        self.Gradient.setColorAt(.4, QtCore.Qt.white)
        self.Gradient.setColorAt(.2, QtCore.Qt.red)
        self.Painter.setBrush(self.Gradient)

        self.Painter.drawPie(self.MainRect, 225.0*16, self.Value*16)
        self.Painter.restore()

        self.Painter.setBrush(QtGui.QBrush(self.Background.scaled(self.Rect.size())))
        self.Painter.drawEllipse(self.RefillRect)

        self.Painter.end()

应用程序每秒更新仪表 60 次(60Hz 显示),这在我的开发机器上很容易完成。但是,当我在 RPi2 上运行 cProfile 超过 10 秒的执行时间(600 次更新)时,大约需要 50 秒才能完成,而 paintEvent() 是主要瓶颈。我已将 QT4Widget 类更改为 QOpenGLWidget,但未显示仪表,并且不会产生任何错误。

例如

class Qt5Widget(QtWidgets.QOpenGLWidget):

我可以将现有的 paintEvent QPainter.drawPie、QPainter.drawPixmap 和 QPainter.drawEllipse 函数与 QOpenGLWidget 一起使用,还是我需要完全重新开始才能利用 QOpenGLWidget 的硬件加速功能?

编辑:Qt5 c++ 文档在 QPainter 类上声明如下:

OpenGL 2.0 (ES) - 此后端是硬件加速图形的主要后端。它可以在支持 OpenGL 2.0 或 OpenGL/ES 2.0 规范的台式机和嵌入式设备上运行。这包括过去几年生产的大多数图形芯片。该引擎可以通过在 QOpenGLWidget 上使用 QPainter 来启用。

鉴于此定义,我在 QOpenGLWidget 上维护现有 QPainter() 函数的方法是否正确?如果是,为什么什么都没有显示?

【问题讨论】:

  • 不知什么原因,我刚刚在 RPi2 上测试了更新后的 QOpenGLWidget 类,它运行良好,所以我的开发机器上可能没有正确的 OpenGL 版本。
  • 也许您可以发布该评论作为答案?

标签: python qt pyqt pyqt5


【解决方案1】:

根据 QT5 文档,QPainter() 类可以在 QOpenGLWidget 上使用,就像在基于光栅的 QWidget 上使用一样。因此,将所有 QWidget 类更改为 QOpenGLWidget 类应该启用 QPainter() 类的硬件加速操作,这是我在我的实例中发现的。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-03-29
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多