我的目标是从 PaintEvents 创建 gif 或视频,并在 QWidget(窗口)上显示。
我尝试将框架绘制到 QImage 上,然后将其渲染到 QWidget 上,但遇到了一些错误。我不确定为什么会出现这样的错误,画家只是在图像上绘画,并且从文档中它说我可以在 end() 之后渲染绘画设备(当我确实将其放在 end 之后时,它会因为不同的原因而抱怨)。
结束()之前
QPainter::begin: A paint device can only be painted by one painter at a time.
QWidget::render: Cannot render with an inactive painter
end()之后,我不应该继承QWidget吗?
QWidget::repaint: Recursive repaint detected
QPainter::begin: A paint device can only be painted by one painter at a time.
QPainter::fillRect: Painter not active
QPainter::scale: Painter not active
QPainter::drawPoints: Painter not active
QPainter::end: Painter not active, aborted
QPainter::begin: A paint device can only be painted by one painter at a time.
QWidget::render: Cannot render with an inactive painter
class PlotWidget(QWidget):
def __init__(self, parent=None):
super().__init__(parent)
self._timer = QTimer(self)
self._timer.setInterval(100)
self._timer.timeout.connect(self.frame)
self._points = QPointList()
self._qimg = QImage(WIDTH, HEIGHT, QImage.Format_RGB32)
# I simplified the frame def
def frame(self):
self._points.clear()
self._points.append(QPoint(0,0))
self.update()
def paintEvent(self, event):
with QPainter(self._qimg) as painter:
rect = QRect(QPoint(0, 0), self.size())
painter.fillRect(rect, Qt.white)
painter.scale(WIDTH / self._sizeX, HEIGHT / self._sizeY)
painter.drawPoints(self._points)
self.render(self._qimg)
self._qimg.save('test.png', 'PNG') # Id like to later make it into a video. Preferably hold img in memory and append frame to video.
我简化了我设想的解决方案的版本。 我使用 imageio 能够通过在每次迭代时附加帧来保存为视频。
您需要 pip install imageio 和 imageio[ffmpeg]
import yaml, os, imageio, numpy as np
from PySide6.QtWidgets import QWidget
from PySide6.QtCore import QPoint, QRect, QTimer, Qt
from PySide6.QtGui import QPainter, QPointList
WIDTH = 720
HEIGHT = 720
class PlotWidget(QWidget):
def __init__(self, parent=None):
super().__init__(parent)
self._timer = QTimer(self)
self._timer.setInterval(100)
self._timer.timeout.connect(self.frame)
self._points = QPointList()
self.setFixedSize(WIDTH, HEIGHT)
self._totalFrames = 10
self._vid_writer = imageio.get_writer('video.avi', fps=10)
def closeEvent(self, event):
self._vid_writer.close()
self._timer.stop()
event.accept()
def frame(self):
self._points.clear()
self._points.append(QPoint(0,0))
if self._totalFrames > 0:
self.update()
pixmap = self.grab()
qimg = pixmap.toImage()
array = np.ndarray((qimg.height(), qimg.width(), 3), buffer=qimg.constBits(), strides=[qimg.bytesPerLine(), 3, 1], dtype=np.uint8)
if not self._vid_writer.closed:
self._vid_writer.append_data(array)
else:
self._timer.stop()
self._vid_writer.close()
self._totalFrames -= 1
def paintEvent(self, event):
with QPainter(self) as painter:
rect = QRect(QPoint(0, 0), self.size())
painter.fillRect(rect, Qt.white)
painter.drawPoints(self._points)