我有一个PyQt5应用程序,其中一个按钮触发与串行设备的通信。当应用程序运行时,它还可以从相机中获取图像。然而,当串行通信忙于读取/写入时,GUI不会更新,并且来自相机的图像不会显示。
我试着用3个独立的线程来解决这个问题——1:GUI,2:serial comm,3:image grab。它们之间的通信是由信号完成的。不幸的是,当我用信号通知第二个线程进行通信时,第一个线程(GUI(不会更新。
布局看起来基本上是这样的:
Thread1 = GUI:
signal to Thread2, when serial comm requested
slot for Thread3, for image data grabbed from device
Thread2 = Serial comm:
slot for Thread1, for data to be send via serial port
Thread3 = Image grab:
signal to Thread1, when new image data is available
因此,当我需要通过串行端口发送一些东西时,Thread1会向Thread2发出一个信号,然后应该继续执行其消息循环,例如对来自Thread3的信号做出反应并绘制新图像。在串行通信线程中完成所有操作之前,Thread2的信号似乎一直处于阻塞状态。
Thread2中的插槽如下所示:
@pyqtSlot(int, int, int)
def motor_move(self, motor, direction, steps):
"""
Move motor one step in given direction.
Parameters
----------
motor : int
Motor index.
direction : int
Direction.
Returns
-------
None.
"""
if self._motor.serial_port:
self._motor.motor_move(motor, steps, direction) # here the serial communication happens
现在的问题是:如何在串行端口繁忙时取消阻止GUI?我可以发送一些返回值来表示信号已被处理吗?
问题是由发出的信号和插槽之间的连接类型引起的。
以前我用过:
.connect(self._move_thread.motor_move)
当发射信号PyQt5时,确定应当建立什么类型的连接。在这种情况下,总是决定使用Qt.DirectConnection
,它立即运行插槽,但等待(!(直到插槽返回。这显示在输出中:
Arduino got: " " # what I have sent
0.0 5.0 # slot takes 5 seconds to return
Done # this is the signaling thread continuing after the slot returns
使用:
.connect(self._move_thread.motor_move, , type=Qt.QueuedConnection)
插槽的处理在EventLoop中排队,并且信号线程不等待插槽返回。现在的输出是:
Arduino got: " " # what I have sent
Done # this is the signaling thread continuing immediately after emitting the signal
0.0 5.0 # slot takes 5 seconds to return