How to run two infinite loops in PyQt5 GUI?(如何在PyQt5GUI中运行两个无限循环?)
本文介绍了如何在PyQt5GUI中运行两个无限循环?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!
问题描述
我正在尝试使用pyqt5构建GUI。在图形用户界面中,我需要通过WiFi从树莓圆周率摄像头流传输一段视频。我需要向树莓派发送游戏板输入。我的代码如下:import sys,time,math
import cv2
import numpy as np
from PyQt5 import QtCore,QtGui,QtWidgets
from PyQt5 import uic
from PyQt5.QtCore import pyqtSlot
from PyQt5.QtGui import QImage,QPixmap
from PyQt5.QtWidgets import QDialog,QApplication
import urllib.request
import threading
import paho.mqtt.client as mqtt
import inputs
m1="0"
broker_ip="computerIP"
url="http://raspberrypiIP/html/cam_pic.php"
#this function get raspberry pi camera video to laptop via WiFi
def url_to_image(url):
with urllib.request.urlopen(url) as resp:
image = np.asarray(bytearray(resp.read()),dtype ="uint8")
image = cv2.imdecode(image,cv2.IMREAD_COLOR)
return image
def on_connect(client, userdata, flags, rc):
client.subscribe("arm")
def on_message(client, userdata, msg):
print (msg.payload)
#mqtt is used to send data from laptop to raspberrypi
client = mqtt.Client()
client.on_connect = on_connect
client.on_message = on_message
client.connect(broker_ip, 1883, 60)
threading.Thread(target=client.loop_forever).start()
def Stop1():
m1="0,0,0,0"
client.publish("arm",str(m1))
def Forward1():
m1="0,0,100,100"
client.publish("arm",str(m1))
def Reverse1():
m1="0,0,-100,-100"
client.publish("arm",str(m1))
def cnsl(): # this function detect the gamepad input
while True:
events=inputs.get_gamepad()
for event in events:
if event.code=="ABS_Y" and event.state>1000:
Forward1()
elif event.code=="ABS_Y" and event.state<-1000:
Reverse1()
elif event.code=="ABS_Y" and event.state==128:
Stop1()
class test1(QtWidgets.QMainWindow):
def __init__(self,*args,**kwargs):
super().__init__(*args,**kwargs)
uic.loadUi("test1.ui",self)
def slot1(self): # this function runs when Pushbutton is clicked
threadVideo=threading.Thread(target=self.onClicked())
threadConsol=threading.Thread(target=self.cnsl())
threadVideo.start()
threadConsol.start()
threadVideo.join()
threadConsol.join()
@pyqtSlot()
# this function display the raspberrypi video in the buited GUI
def onClicked(self):
print ("video")
while (True):
img=url_to_image(url)
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
qformat=QImage.Format_Indexed8
if len(img.shape)==3:
if (img.shape[2])==4:
qformat=QImage.Format_RGBA888
else:
qformat=QImage.Format_RGB888
img=QImage(img,img.shape[1],img.shape[0],qformat)
img=img.rgbSwapped()
self.label_3.setPixmap(QPixmap.fromImage(img))
if cv2.waitKey(1) & 0xFF == ord('q'):
break
app=QtWidgets.QApplication(sys.argv)
window=test1()
window.show()
app.exec_()
当我运行此代码时,GUI中显示视频流。但我不能发送游戏板输入。我也试过用两个纽扣。但这两个按钮并不同时工作。有谁知道吗?
推荐答案
在操作码中有一些小错误,如:
threading.Thread(target=foo())
因为它相当于:
res = foo()
threading.Thread(target=res)
如您所见,任务不是在辅助线程中执行,而是在初始线程中执行。
另一个错误是使用join(),因为此方法会阻塞初始线程的执行,直到辅助线程中执行的线程结束,而这显然不是您想要的。
另一个小错误是,不需要在辅助线程中使用LOOP_EVERVER方法,只需执行start()函数即可。
此外,还应考虑不应从另一个线程更新GUI,而应通过信号将信息发送到主线程(其中必须更新GUI)。
综合以上考虑,解决方案为:
import sys
import threading
from PyQt5 import QtCore, QtGui, QtWidgets, uic
import sip
import paho.mqtt.client as mqtt
import inputs
import cv2
import numpy as np
import urllib.request
broker_ip = "computerIP"
url = "http://raspberrypiIP/html/cam_pic.php"
def url_to_image(url):
with urllib.request.urlopen(url) as resp:
image = np.asarray(bytearray(resp.read()), dtype="uint8")
image = cv2.imdecode(image, cv2.IMREAD_COLOR)
return image
class GamepadManager:
def __init__(self):
self.client = mqtt.Client()
self.client.on_connect = self.on_connect
self.client.on_message = self.on_message
self.client.connect(broker_ip, 1883, 60)
def start(self):
self.client.start()
threading.Thread(target=self._init_bucle, daemon=True).start()
def on_connect(self, client, userdata, flags, rc):
self.client.subscribe("arm")
def on_message(self, client, userdata, msg):
print(msg.payload)
def stop_arm(self):
m1 = "0,0,0,0"
self.client.publish("arm", m1)
def forward_arm(self):
m1 = "0,0,100,100"
self.client.publish("arm", m1)
def reverse_arm(self):
m1 = "0,0,-100,-100"
self.client.publish("arm", m1)
def _init_bucle(self):
while True:
events = inputs.get_gamepad()
for event in events:
if event.code == "ABS_Y" and event.state > 1000:
self.forward_arm()
elif event.code == "ABS_Y" and event.state < -1000:
self.reverse_arm()
elif event.code == "ABS_Y" and event.state == 128:
self.stop_arm()
class VideoManager(QtCore.QObject):
imageChanged = QtCore.pyqtSignal(QtGui.QImage)
def start(self):
threading.Thread(target=self._request_video, daemon=True).start()
def _request_video(self):
while True:
img = url_to_image(url)
qformat = QtGui.QImage.Format_Indexed8
if len(img.shape) == 3:
if (img.shape[2]) == 4:
qformat = QtGui.QImage.Format_RGBA888
else:
qformat = QtGui.QImage.Format_RGB888
img = QtGui.QImage(img, img.shape[1], img.shape[0], qformat)
img = img.rgbSwapped()
if not sip.isdeleted(self):
self.imageChanged.emit(img)
class MainWindow(QtWidgets.QMainWindow):
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
uic.loadUi("test1.ui", self)
@QtCore.pyqtSlot(QtGui.QImage)
def update_label(self, image):
pixmap = QtGui.QPixmap.fromImage(image)
self.label_3.setPixmap(pixmap)
def main():
app = QtWidgets.QApplication(sys.argv)
w = MainWindow()
w.show()
gamepad_manager = GamepadManager()
video_manager = VideoManager()
video_manager.imageChanged.connect(w.update_label)
gamepad_manager.start()
video_manager.start()
sys.exit(app.exec_())
if __name__ == "__main__":
main()
这篇关于如何在PyQt5GUI中运行两个无限循环?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持编程学习网!
织梦狗教程
本文标题为:如何在PyQt5GUI中运行两个无限循环?


基础教程推荐
猜你喜欢
- 在 Python 中将货币解析为数字 2022-01-01
- kivy 应用程序中的一个简单网页作为小部件 2022-01-01
- matplotlib 设置 yaxis 标签大小 2022-01-01
- Python 中是否有任何支持将长字符串转储为块文字或折叠块的 yaml 库? 2022-01-01
- 对多索引数据帧的列进行排序 2022-01-01
- Kivy 使用 opencv.调整图像大小 2022-01-01
- 比较两个文本文件以找出差异并将它们输出到新的文本文件 2022-01-01
- 究竟什么是“容器"?在蟒蛇?(以及所有的 python 容器类型是什么?) 2022-01-01
- 在 Django Admin 中使用内联 OneToOneField 2022-01-01
- Python,确定字符串是否应转换为 Int 或 Float 2022-01-01