如何将Qt Widget快照存入变量?并导出动态绘图为视频
Qt Widget动画绘图导出为视频的完整方案
一、将PyQtGraph绘图快照存入变量(无需保存到文件)
PyQtGraph的ImageExporter底层依赖Qt的QImage实现渲染,我们可以绕过文件存储逻辑,直接获取渲染后的图像对象,再转换为Pillow图像或bytearray:
方法1:基于PyQtGraph Exporter获取图像
import pyqtgraph as pg from pyqtgraph.exporters import ImageExporter from PIL import Image plt = pg.plot([1, 5, 2, 4, 3]) exporter = ImageExporter(plt.plotItem) # 自定义导出尺寸(可选,默认使用Widget原尺寸) exporter.parameters()['width'] = plt.width() exporter.parameters()['height'] = plt.height() # 直接获取QImage对象 qimage = exporter.exportToImage() # 转换为Pillow图像 pil_img = Image.fromqimage(qimage) # 转换为PNG格式的bytearray png_bytes = bytes(qimage.saveToData())
方法2:通用Qt Widget截图(适用于所有Qt控件)
如果不限于PyQtGraph,所有Qt Widget都可以用内置的grab()方法直接截图:
from PyQt5.QtWidgets import QApplication import pyqtgraph as pg from PIL import Image app = QApplication([]) plt = pg.plot([1, 5, 2, 4, 3]) # 对Widget直接截图 qimage = plt.grab() # 转Pillow图像 pil_img = Image.fromqimage(qimage) # 转bytearray png_bytes = bytes(qimage.saveToData())
二、捕获动画的帧序列
要捕获动态变化的Widget帧,需要在动画更新的时机触发截图,两种常见实现方式:
方式1:定时捕获(适合周期性动画)
import pyqtgraph as pg from PyQt5.QtCore import QTimer from PIL import Image app = QApplication([]) plt = pg.plot() data = [1, 5, 2, 4, 3] current_idx = 0 frame_list = [] def update_and_capture(): global current_idx # 更新绘图(模拟动画) current_idx = (current_idx + 1) % len(data) plt.plot([current_idx, data[current_idx]], clear=True) # 捕获当前帧 qimage = plt.grab() frame_list.append(Image.fromqimage(qimage)) # 每100ms更新一次(对应10fps) timer = QTimer() timer.timeout.connect(update_and_capture) timer.start(100) # 运行5秒后停止捕获 QTimer.singleShot(5000, timer.stop) app.exec_()
方式2:绘图更新时捕获(适合自定义实时动画)
如果你的动画是通过PlotDataItem实时更新,可在更新回调中嵌入捕获逻辑:
import pyqtgraph as pg from PyQt5.QtCore import QTimer import numpy as np from PIL import Image app = QApplication([]) plt = pg.plot() curve = plt.plot() x = np.linspace(0, 10, 100) current_t = 0 frame_list = [] def update_curve_and_capture(): global current_t current_t += 0.1 # 更新曲线数据(模拟正弦波动画) curve.setData(x, np.sin(x + current_t)) # 捕获当前帧 qimage = plt.grab() frame_list.append(Image.fromqimage(qimage)) # 每50ms更新一次(对应20fps) timer = QTimer() timer.timeout.connect(update_curve_and_capture) timer.start(50) # 运行3秒后停止 QTimer.singleShot(3000, timer.stop) app.exec_()
三、将帧序列合成为视频
用MoviePy快速合成(推荐)
安装依赖:pip install moviepy
from moviepy.editor import ImageSequenceClip # 设置帧率(需和捕获时的帧率一致) fps = 10 # 合成视频并保存 clip = ImageSequenceClip(frame_list, fps=fps) clip.write_videofile("animation.mp4", codec="libx264")
用OpenCV精细控制
安装依赖:pip install opencv-python
import cv2 import numpy as np fps = 10 width, height = frame_list[0].size # 初始化视频写入器 fourcc = cv2.VideoWriter_fourcc(*'mp4v') video_writer = cv2.VideoWriter("animation.mp4", fourcc, fps, (width, height)) for frame in frame_list: # Pillow图像转OpenCV格式(RGB转BGR) cv_frame = cv2.cvtColor(np.array(frame), cv2.COLOR_RGB2BGR) video_writer.write(cv_frame) video_writer.release()
内容的提问来源于stack exchange,提问作者Rik
相关产品推荐
相关产品推荐

