【发布时间】:2019-11-22 13:21:27
【问题描述】:
我有多个通过 wifi 无线连接的摄像头,我正在尝试将数据流式传输到客户端,客户端会在 GUI 上显示流。
我的问题是 pyqtgraph ImageItems 似乎在大约 30 秒后停止重新绘制,或者如果我点击窗口外,或者如果我调整其中一张图像的控件。之后,我可以通过调整窗口大小来重新绘制图像,但这有点乏味。
我想也许 pyqtgraph 不是线程安全的,但我什至不知道我是否使用了真正的线程,因为我必须让所有东西都通过 Qt (QThread) 运行才能正常工作。
我发现一些论坛帖子显示了与此类似的问题。 The first one 重定向到 here 解释说你可以使用名为 NSAppSleepDisabled 的东西,但这似乎只在 OSX 上,我正在运行 Windows 10。The second one 解释说他们的整个 GUI 冻结,而我没有遇到这个问题,只有 ImageItem 冻结,其余的 GUI 都是响应式的。
这些是我的导入
import time
from multiprocessing import Queue
from threading import Lock
from queue import Empty
import pyqtgraph as pg
from PyQt5.QtCore import QThread
为了保持我的软件可扩展,我使用工作线程来管理传入的图像数据,为了保持 ImageView 的线程安全,我添加了一个锁:
graph_lock = Lock()
class WindowUpdater(QThread):
stop_q = Queue()
def __init__(self, cam_q: Queue, img_control: pg.ImageView, **kwargs):
super().__init__(**kwargs)
self.q = cam_q
self.c = img_control
def run(self) -> None:
while self.stop_q.empty():
try:
timg = self.q.get_nowait()
graph_lock.acquire(True)
self.c.setImage(timg.frame)
self.c.invalidate()
graph_lock.release()
except Empty:
time.sleep(0.1)
然后主应用程序处理将这些线程链接到传入数据
app = QApplication(sys.argv)
window = QMainWindow()
grid = QGridLayout()
grid.setSpacing(10)
widg = QWidget()
widg.setLayout(grid)
window.setCentralWidget(widg)
window.show()
window.setGeometry(300, 300, 500, 400)
window.show()
threads = []
for i, h in enumerate(hosts):
img = pg.ImageView(window)
grid.addWidget(img, i, 0)
img_item = pg.ImageItem()
img.addItem(img_item)
threads.append(WindowUpdater(img_queue, img)
for t in threads:
t.start()
sys.exit(app.exec_())
其中hosts 是用于连接的主机名列表,img_queue 是特定于该主机的摄像头流的多处理队列。
有人知道为什么同时运行多个 pyqtgraph ImageView 或 ImageItem 实例会导致这里出现问题吗?
【问题讨论】:
标签: python pyqt5 python-multithreading qthread pyqtgraph