我正在尝试创建一个简单的休息端点,当点击时,它会更改程序本身安装的托盘图标的状态。
我相信我需要 Flask 和 QApplication 在不同的线程中运行,我尝试这样做。
但是我不熟悉Python,很可能我在下面做错了什么:
import sys
import asyncio
from PyQt6.QtGui import QIcon
from PyQt6.QtWidgets import (
QSystemTrayIcon,
QApplication,
QWidget
)
from flask import Flask
async def gui():
app = QApplication(sys.argv)
w = QWidget()
trayIcon = QSystemTrayIcon(QIcon("disconnected.png"), w)
trayIcon.show()
print("running gui")
return app.exec()
async def rest():
app1 = Flask(__name__)
@app1.route("/connect")
def connect():
return "I will signal gui to change icon to connected"
@app1.route("/disconnect")
def disconnect():
return "I will signal gui to change icon to disconnected"
print("creating rest endpoint")
return app1.run()
async def main():
return await asyncio.gather(gui(), rest() )
if __name__ == "__main__":
asyncio.run(main())
当我运行上面的代码时,我只看到“正在运行 gui”,并且我可以看到托盘图标被安装到状态栏。我没有看到“创建休息端点”
如果我注释掉“return app.exec()”。我看到“正在创建休息端点”并且可以访问端点,但没有看到托盘图标。
我错过了什么?
额外信息:这是我的
Pipfile
(使用pipenv
)
[[source]]
url = "https://pypi.org/simple"
verify_ssl = true
name = "pypi"
[packages]
pyqt6 = "*"
flask = {extras = ["async"], version = "*"}
[dev-packages]
[requires]
python_version = "3.10"
ayncio
时,
await
很有用 - 在 app.run()
和 app.exec()
内部 - 但据我所知,Qt
和 Flask
不这样做。 (但也许 Flask
有使用 asyncio
的版本)
您可能需要使用线程在单独的线程中运行程序(或者一个程序在单独的线程中运行,其他程序在当前线程中运行)。
版本 1:两个程序都在单独的线程中
def gui(): # without `async
#...
def rest(): # without `async
#...
if __name__ == "__main__":
from threading import Thread
t1 = Thread(target=gui)
t2 = Thread(target=rest)
t1.start()
t2.start()
# it blocks this function and wait for end of threads
t1.join()
t2.join()
版本 2:一个程序在单独的线程中,另一个程序在当前线程中
def gui(): # without `async
#...
def rest(): # without `async
#...
if __name__ == "__main__":
from threading import Thread
t1 = Thread(target=gui)
t1.start()
rest() # it blocks this function
# wait for end of thread
t1.join()
完整的工作代码
import sys
import asyncio
from PyQt6.QtGui import QIcon
from PyQt6.QtWidgets import (
QSystemTrayIcon,
QApplication,
QWidget
)
from flask import Flask
def gui():
app = QApplication(sys.argv)
w = QWidget()
trayIcon = QSystemTrayIcon(QIcon("disconnected.png"), w)
trayIcon.show()
print("running gui")
app.exec()
def rest():
app = Flask(__name__)
@app.route("/connect")
def connect():
return "I will signal gui to change icon to connected"
@app.route("/disconnect")
def disconnect():
return "I will signal gui to change icon to disconnected"
print("creating rest endpoint")
app.run()
def version_1():
from threading import Thread
t1 = Thread(target=gui)
t2 = Thread(target=rest)
t1.start()
t2.start()
# it blocks this function and wait for end of threads
t1.join()
t2.join()
def version_2()
from threading import Thread
t1 = Thread(target=gui)
t1.start()
rest() # it blocks this function
# wait for end of thread
t1.join()
if __name__ == "__main__":
#version_1()
version_2()
编辑:
我不确定这些线程是否可以使用 Qt 信号进行通信。他们可能需要使用 queue 进行通信,并且
Qt
可能需要 QTimer
定期检查 queue
中是否有新信息。
其他想法:
Flask
应该有url
返回当前状态(连接或断开连接的信息)并且Qt
可以使用QTime
和可能的QtNetwork.QNetworkRequest(QtCore.QUrl(url))
来检查此状态。这样您就可以随时使用其他 GUI 框架来检查状态。或者您可以在文本控制台中检查状态(即使用 curl
、wget
)
如果您打算仅使用
Flask
来更改 Qt
中的状态,那么也许您应该使用 QtNetwork
直接在 Qt
中运行服务器,而不使用 Flask
。