Python PyQt5和Asyncio
是否可以保持UDP服务器作为异步函数运行以接收数据,然后将其传递给(PyQt5)小部件,该小部件也作为异步函数运行 其思想是,当进入服务器的数据被更新时,它也会更新小部件 我已经有了一个简单的UDP服务器和一个(PyQt5)小部件,它们独立地工作得很好,但我正在努力将它们结合起来,使它们都异步运行并交换数据(服务器将数据传输到小部件) [更新] 下面是我正在试用的小部件Python PyQt5和Asyncio,python,pyqt,pyqt5,python-asyncio,coroutine,Python,Pyqt,Pyqt5,Python Asyncio,Coroutine,是否可以保持UDP服务器作为异步函数运行以接收数据,然后将其传递给(PyQt5)小部件,该小部件也作为异步函数运行 其思想是,当进入服务器的数据被更新时,它也会更新小部件 我已经有了一个简单的UDP服务器和一个(PyQt5)小部件,它们独立地工作得很好,但我正在努力将它们结合起来,使它们都异步运行并交换数据(服务器将数据传输到小部件) [更新] 下面是我正在试用的小部件 import sys from PyQt5 import QtWidgets, QtCore, QtGui from PyQt
import sys
from PyQt5 import QtWidgets, QtCore, QtGui
from PyQt5.QtWidgets import QApplication, QMainWindow
import asyncio
class Speedometer(QMainWindow):
angleChanged = QtCore.pyqtSignal(float)
def __init__(self, parent = None):
QtWidgets.QWidget.__init__(self, parent)
self._angle = 0.0
self._margins = 20
self._pointText = {0: "40", 30: "50", 60: "60", 90: "70", 120: "80",
150:"" , 180: "", 210: "",
240: "0", 270: "10", 300: "20", 330: "30", 360: ""}
def paintEvent(self, event):
painter = QtGui.QPainter()
painter.begin(self)
painter.setRenderHint(QtGui.QPainter.Antialiasing)
painter.fillRect(event.rect(), self.palette().brush(QtGui.QPalette.Window))
self.drawMarkings(painter)
self.drawNeedle(painter)
painter.end()
def drawMarkings(self, painter):
painter.save()
painter.translate(self.width()/2, self.height()/2)
scale = min((self.width() - self._margins)/120.0,
(self.height() - self._margins)/60.0)
painter.scale(scale, scale)
font = QtGui.QFont(self.font())
font.setPixelSize(10)
metrics = QtGui.QFontMetricsF(font)
painter.setFont(font)
painter.setPen(self.palette().color(QtGui.QPalette.Shadow))
i = 0
while i < 360:
if i % 30 == 0 and (i <150 or i > 210):
painter.drawLine(0, -40, 0, -50)
painter.drawText(-metrics.width(self._pointText[i])/2.0, -52,
self._pointText[i])
elif i <135 or i > 225:
painter.drawLine(0, -45, 0, -50)
painter.rotate(15)
i += 15
painter.restore()
def drawNeedle(self, painter):
painter.save()
painter.translate(self.width()/2, self.height()/1.5)
painter.rotate(self._angle)
scale = min((self.width() - self._margins)/120.0,
(self.height() - self._margins)/120.0)
painter.scale(scale, scale)
painter.setPen(QtCore.Qt.NoPen)
painter.setBrush(self.palette().brush(QtGui.QPalette.Shadow))
painter.drawPolygon(
QtGui.QPolygon([QtCore.QPoint(-10, 0), QtCore.QPoint(0, -45), QtCore.QPoint(10, 0),
QtCore.QPoint(0, 5), QtCore.QPoint(-10, 0)])
)
painter.setBrush(self.palette().brush(QtGui.QPalette.Highlight))
painter.drawPolygon(
QtGui.QPolygon([QtCore.QPoint(-5, -25), QtCore.QPoint(0, -45), QtCore.QPoint(5, -25),
QtCore.QPoint(0, -30), QtCore.QPoint(-5, -25)])
)
painter.restore()
def sizeHint(self):
return QtCore.QSize(150, 150)
def angle(self):
return self._angle
# @pyqtSlot(float)
def setAngle(self, angle):
if angle != self._angle:
self._angle = angle
self.angleChanged.emit(angle)
self.update()
angle = QtCore.pyqtProperty(float, angle, setAngle)
@staticmethod
def mainLoopSpd():
while True:
app = QApplication(sys.argv)
window = QtWidgets.QWidget()
spd = Speedometer()
spinBox = QtWidgets.QSpinBox()
#spd.setAngle(100)
spinBox.setRange(0, 359)
spinBox.valueChanged.connect(spd.setAngle)
layout = QtWidgets.QVBoxLayout()
layout.addWidget(spd)
layout.addWidget(spinBox)
window.setLayout(layout)
window.show()
app.exec_()
#await asyncio.sleep(1)
sys.exit(app.exec_())
下面是调用这两个函数的主要函数
from speedometer import Speedometer
import asyncio
from pyServer import UDPserver
class mainApp:
#vel = 0
def __init__(self):
self.velo = 0
self.queue= asyncio.Queue(0)
async def server(self):
while True:
self.velo= UDPserver.mainLoopUDPserver()
print("THIS IS VELO{}",self.velo)
#await self.queue.put(self.velo)
#vel= await self.queue.get()
#return vel
#print("ASSDASDSADSD{}",vel)
await asyncio.sleep(0)
#print("HI, vel Received={}",self.veloc)
#return velo
async def widget(self):
while True:
#vel = await self.queue.get()
#print("Hola xDDDDDDD", vel)
print(">>>>>>>>>>>>>>>NextIteration>>>>>>>>>>>>>>")
await Speedometer.mainLoopSpd()
await asyncio.sleep(0)
loop= asyncio.get_event_loop()
mApp= mainApp()
loop.create_task(mApp.server())
loop.create_task(mApp.widget())
loop.run_forever()
因此,当我运行它时,它会监听服务器,一旦我开始通过UDP发送数据,它就会接收第一条数据并打开运行正常的小部件,但它会使服务器停止,它不再接收任何数据
正如您在评论中所看到的,我也一直在使用异步IO队列,但实际上我什么都没有
我的理想场景是服务器接收数据并将其传递给小部件,以便使用传入的数据进行更新,但目前我只希望它们都独立工作
谢谢应该清楚,您的UDP服务器不是异步运行的 asyncio的逻辑是所有东西都使用eventloop作为基础,默认情况下Qt不支持它,因此必须使用(
python-m pip install qasync
)和(python-m pip install asyncqt
)等库
考虑到上述情况,解决方案是:
车速表.py
从PyQt5导入QtCore、QtGui、qtwidget
类速度计(qtwidts.QWidget):
角度更改=QtCore.pyqtSignal(浮动)
def uuu init uuu(self,parent=None):
super()。\uuuu init\uuuu(父级)
自转角=0.0
自选页边距=20
self.\u pointText={
0: "40",
30: "50",
60: "60",
90: "70",
120: "80",
150: "",
180: "",
210: "",
240: "0",
270: "10",
300: "20",
330: "30",
360: "",
}
def paintEvent(自身,事件):
painter=QtGui.QPainter(自)
painter.setRenderHint(QtGui.QPainter.Antialiasing)
painter.fillRect(event.rect(),self.palete().brush(QtGui.QPalette.Window))
自绘制标记(油漆工)
自吸针(油漆工)
def图纸标记(自身、油漆工):
保存
painter.translate(self.width()/2,self.height()/2)
刻度=最小值(
(self.width()-self._边距)/120.0,
(自高度()-self._边距)/60.0,
)
画师:比例(比例,比例)
font=QtGui.QFont(self.font())
font.setPixelSize(10)
metrics=QtGui.QFontMetricsF(字体)
painter.setFont(字体)
painter.setPen(self.palete().color(QtGui.qpalete.Shadow))
i=0
而我<360:
如果i%30==0且(i<150或i>210):
油漆工.抽绳(0,-40,0,-50)
绘画文本(
-metrics.width(self.\u pointText[i])/2.0,-52,self.\u pointText[i]
)
如果i<135或i>225:
油漆工.抽绳(0,-45,0,-50)
油漆工。旋转(15)
i+=15
恢复
def抽油针(自身、油漆工):
保存
painter.translate(self.width()/2,self.height()/1.5)
油漆工。旋转(自身角度)
刻度=最小值(
(self.width()-self._边距)/120.0,
(自高度()-self._边距)/120.0,
)
画师:比例(比例,比例)
painter.setPen(QtCore.Qt.NoPen)
painter.setBrush(self.palete().brush(QtGui.qpalete.Shadow))
画师(
QtGui.QPolygon(
[
QtCore.QPoint(-10,0),
QtCore.QPoint(0,-45),
QtCore.QPoint(10,0),
QtCore.QPoint(0,5),
QtCore.QPoint(-10,0),
]
)
)
painter.setBrush(self.palete().brush(QtGui.qpalete.Highlight))
画师(
QtGui.QPolygon(
[
QtCore.QPoint(-5,-25),
QtCore.QPoint(0,-45),
QtCore.QPoint(5,-25),
QtCore.QPoint(0,-30),
QtCore.QPoint(-5,-25),
]
)
)
恢复
def sizeHint(自身):
返回QtCore.QSize(150150)
def角度(自):
返回自转角
@QtCore.pyqtSlot(浮动)
def设置角度(自身、角度):
如果角度!=自转角:
自身角度=角度
self.angleChanged.emit(角度)
self.update()
角度=QtCore.pyqtProperty(浮点、角度、设置角度)
如果名称=“\uuuuu main\uuuuuuuu”:
导入系统
导入异步
从asyncqt导入QEventLoop
app=qtwidts.QApplication(sys.argv)
循环=QEventLoop(应用程序)
asyncio.set\u event\u循环(循环)
带循环:
w=速度表()
w、 角度=10
w、 show()
loop.run_forever()
server.py
导入异步IO
从PyQt5导入QtCore
类UDPserver(QtCore.QObject):
dataChanged=QtCore.pyqtSignal(浮点,浮点,浮点,浮点)
def uuu init uuu(self,parent=None):
super()。\uuuu init\uuuu(父级)
自身运输=无
自身计数器消息=0
@财产
def传输(自):
返回自我运输
def连接(自行、运输):
自我运输=运输
接收到def数据报(自身、数据、地址):
自身计数器信息+=1
打印(“收到的Mssg数量:{}”。格式(自我计数器消息))
message=data.decode()
东乌德
from speedometer import Speedometer
import asyncio
from pyServer import UDPserver
class mainApp:
#vel = 0
def __init__(self):
self.velo = 0
self.queue= asyncio.Queue(0)
async def server(self):
while True:
self.velo= UDPserver.mainLoopUDPserver()
print("THIS IS VELO{}",self.velo)
#await self.queue.put(self.velo)
#vel= await self.queue.get()
#return vel
#print("ASSDASDSADSD{}",vel)
await asyncio.sleep(0)
#print("HI, vel Received={}",self.veloc)
#return velo
async def widget(self):
while True:
#vel = await self.queue.get()
#print("Hola xDDDDDDD", vel)
print(">>>>>>>>>>>>>>>NextIteration>>>>>>>>>>>>>>")
await Speedometer.mainLoopSpd()
await asyncio.sleep(0)
loop= asyncio.get_event_loop()
mApp= mainApp()
loop.create_task(mApp.server())
loop.create_task(mApp.widget())
loop.run_forever()