警告
本节包含从C++自动翻译到Python的代码片段,可能存在错误。
光栅窗口示例#
此示例演示了如何使用QWindow
构建基于QPainter
的渲染功能的简化应用。
应用程序入口点#
if __name__ == "__main__": app = QGuiApplication(argc, argv) window = RasterWindow() window.show() sys.exit(app.exec())
基于QWindow
的应用程序的入口点是QGuiApplication
类。它管理GUI应用程序的流程和主要设置。我们传递命令行参数,这些参数可以用来选择某些系统级别的选项。
从这里,我们继续创建我们的窗口实例,然后调用show()
函数来告诉窗口系统,该窗口现在应在屏幕上可见。
一旦完成以上步骤,我们就进入应用程序的事件循环,使应用程序可以运行。
RasterWindow 声明#
from PySide6 import QtGui class RasterWindow(QWindow): Q_OBJECT # public RasterWindow = explicit(QWindow parent = None) virtual void render(QPainter painter) # public slots def renderLater(): def renderNow(): # protected bool event(QEvent event) override def resizeEvent(event): def exposeEvent(event): # private m_backingStore = QScopedPointer()
我们首先包含<QtGui>
头文件。这意味着我们可以使用Qt GUI模块中的所有类。如果需要,类也可以单独包含。
RasterWindow类直接子类自QWindow
,并提供了一个构造函数,该构造函数允许窗口成为另一个QWindow
的子窗口。无父窗口的QWindows在窗口系统中显示为顶级窗口。
该类声明了一个QBackingStore
,这是我们用来管理窗口的后缓冲区的,以便通过QPainter
进行图形渲染。
光栅窗口也在一些其他示例中重复使用,并增加了一些辅助函数,如renderLater()。
RasterWindow 实现#
def __init__(self, parent): super().__init__(parent) , m_backingStore(QBackingStore(self)) setGeometry(100, 100, 300, 200)
在构造函数中,我们创建了backingstore,并将其传递给它需要管理的窗口实例。我们还设置了初始窗口几何形状。
def exposeEvent(self, arg__0): if isExposed(): renderNow()
在调用创建的窗口上的 show()
函数后不久,将调用虚函数 exposeEvent()
来通知我们窗口在窗口系统中的曝光状态已更改。该事件包含曝光的子区域,但由于我们每次都要绘制整个窗口,所以我们没有利用这一点。
isExposed()
函数将告诉我们窗口是否显示。这是必需的,因为即使窗口在窗口系统中被遮挡,也会调用 exposeEvent。如果窗口显示,我们调用 renderNow() 立即绘制窗口。我们想立即绘制以向系统提供一些可视化内容。
def resizeEvent(self, resizeEvent): m_backingStore.resize(resizeEvent.size())
调整大小事件保证在窗口显示在屏幕上之前被调用,并且也会在窗口在屏幕上调整大小的情况下被调用。我们使用这一点来调整后缓冲区的大小,并将绘制延迟到相应的/后续的 expose 事件。
def renderNow(self): if not isExposed(): return rect = QRect(0, 0, width(), height()) m_backingStore.beginPaint(rect) device = m_backingStore.paintDevice() painter = QPainter(device) painter.fillRect(0, 0, width(), height(), QGradient.NightFade) render(painter) painter.end() m_backingStore.endPaint() m_backingStore.flush(rect)
renderNow 函数设置 QWindow
使用 QPainter
渲染其内容所需的所有内容。由于遮挡的窗口将不可见,因此如果窗口在窗口系统中未被暴露,将中止操作。例如,当另一个窗口完全遮挡此窗口时,可能会发生这种情况。
我们通过调用我们想要绘制的区域的 beginPaint()
来开始绘制。然后,我们获取后缓冲区的 QPaintDevice
并创建一个 QPainter
来渲染该绘图设备。
为了避免留下先前渲染的痕迹并从干净的缓冲区开始,我们用白色填充整个缓冲区。然后我们调用虚拟的 render() 函数来实际绘制此窗口。
绘制完成後,我们调用 endPaint() 来表示我们已完成渲染,并使用 flush()
在后缓冲区中提供内容。
def render(self, painter): painter.drawText(QRectF(0, 0, width(), height()), Qt.AlignCenter, "QWindow")
render 函数包含窗口的绘制代码。在这个简例中,我们只在中心绘制字符串“ QWindow
”。
异步渲染
def renderLater(self): requestUpdate()
我们在几个地方遇到了需要立即重新绘制的窗口。在某些情况下,这并不理想,而是应该让应用程序返回到事件循环并安排稍后重新绘制。我们通过请求更新实现这一点,使用requestUpdate()
,系统准备好重新绘制时将会传递。
def event(self, QEvent event): if event.type() == QEvent.UpdateRequest: renderNow() return True return QWindow.event(event)
我们重新实现了虚拟QObject::event()函数来处理更新事件。当事件到来时,我们调用renderNow()立即渲染窗口。