gpt4 book ai didi

python - 如何在 PyQt5 GUI 中运行两个无限循环?

转载 作者:行者123 更新时间:2023-12-04 09:28:29 25 4
gpt4 key购买 nike

我正在尝试使用 pyqt5 构建一个 GUI。在 GUI 中,我需要通过 WiFi 从树莓派相机流式传输视频。我需要将游戏 handle 输入发送到树莓派。我的代码如下:

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 中会显示视频流。但我无法发送游戏 handle 输入。我也试过 2 个按钮。但是两个按钮不能同时工作。有没有人有任何想法?

最佳答案

在 OP 代码中有一些小错误,例如:

threading.Thread(target=foo())
因为它相当于:
res = foo()
threading.Thread(target=res)
正如您所看到的,任务不是在辅助线程中执行,而是在初始线程中执行。
另一个错误是使用 join() ,因为此方法会阻止初始线程的执行,直到在辅助线程中执行的内容结束,显然这不是您想要的。
还有一个小错误是在辅助线程中不需要使用loop_forever方法,只需要执行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()

关于python - 如何在 PyQt5 GUI 中运行两个无限循环?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/62930343/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com