我有多个通过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实例会导致问题吗?
答案 0 :(得分:2)
由于Qt禁止(1),因此您不应从其他线程更新GUI。因此,您必须使用信号来传输信息。
?data.table
class WindowUpdater(QThread):
imageChanged = pyqtSignal(np.ndarray)
stop_q = Queue()
def __init__(self, cam_q: Queue, **kwargs):
super().__init__(**kwargs)
self.q = cam_q
def run(self) -> None:
while self.stop_q.empty():
try:
timg = self.q.get_nowait()
graph_lock.acquire(True)
self.imageChanged.emit(timg.frame)
graph_lock.release()
except Empty:
time.sleep(0.1)