python - 如何每 60 秒更新一次 PyQt5 图标?
问题描述
我是 python 新手,我正在做一个简单的应用程序,其中比特币的价值显示在系统托盘中。我正在使用 PyQt5。
我的问题是:如何每分钟刷新一次值和图标。当我尝试它时,我的菜单将不再起作用。有简单的解决方法吗?
这是我的代码:
import sys
import time
import math
import json
from PyQt5.QtWidgets import QApplication, QSystemTrayIcon, QMenu
from PyQt5.QtGui import QIcon
from urllib.request import urlopen
from time import sleep
app = QApplication(sys.argv)
while True:
# Connecting the api
with urlopen("https://api.alternative.me/v2/ticker/1/") as response:
source = response.read()
data = json.loads(source)
price = (json.dumps(data['data']['1']['quotes']['USD']['price']))
change = (json.dumps(data['data']['1']['quotes']['USD']['percentage_change_1h']))
intPrice = float(price)
intChange = float(change)
roundPrice = round(intPrice,2)
roundStringPrice = str(roundPrice)
# Icon change
if intChange <=0.00:
trayIcon = QSystemTrayIcon(QIcon('icons/down.png'), parent=app)
else:
trayIcon = QSystemTrayIcon(QIcon('icons/up.png'), parent=app)
trayIcon.setToolTip(roundStringPrice + ' USD')
trayIcon.show()
time.sleep(5)
trayIcon.update()
menu = QMenu()
exitAction = menu.addAction('Quit app')
exitAction.triggered.connect(app.quit)
trayIcon.setContextMenu(menu)
sys.exit(app.exec_())
解决方案
不要使用 while True、urlopen 或 time.sleep,因为它们会阻塞事件循环,而是使用带有 QNetworkAccessManager 的 QTimer:
import os.path
import json
from functools import cached_property
from PyQt5.QtCore import pyqtSignal, QObject, QTimer, QUrl
from PyQt5.QtNetwork import QNetworkAccessManager, QNetworkReply, QNetworkRequest
from PyQt5.QtGui import QIcon
from PyQt5.QtWidgets import QApplication, QMenu, QMessageBox, QSystemTrayIcon
CURRENT_DIR = os.path.dirname(os.path.realpath(__file__))
class ApiManager(QObject):
infoChanged = pyqtSignal(float, float)
def __init__(self, parent=None):
super().__init__(parent)
self.manager.finished.connect(self.handle_finished)
@cached_property
def manager(self):
return QNetworkAccessManager()
def start_request(self):
url = QUrl("https://api.alternative.me/v2/ticker/1/")
qrequest = QNetworkRequest(url)
self.manager.get(qrequest)
def handle_finished(self, reply):
if reply.error() != QNetworkReply.NoError:
print(f"code: {reply.error()} message: {reply.errorString()}")
else:
print("successful")
source = reply.readAll().data()
data = json.loads(source)
r = data["data"]["1"]["quotes"]["USD"]
price = r["price"]
change = r["percentage_change_1h"]
self.infoChanged.emit(price, change)
class SystemTrayIcon(QSystemTrayIcon):
def __init__(self, parent=None):
super().__init__(parent)
self.setIcon(QIcon(self.get_resource("icons/up.png")))
self.menu = QMenu()
exitAction = self.menu.addAction("Quit app")
exitAction.triggered.connect(QApplication.quit)
self.setContextMenu(self.menu)
self.manager = ApiManager()
self.manager.infoChanged.connect(self.handle_info_changed)
timer = QTimer(self, timeout=self.manager.start_request, interval=60 * 1000)
timer.start()
self.manager.start_request()
def get_resource(self, path):
return os.path.join(CURRENT_DIR, path)
def handle_info_changed(self, price, change):
icon = (
QIcon(self.get_resource("icons/down.png"))
if change < 0
else QIcon(self.get_resource("icons/up.png"))
)
self.setIcon(icon)
self.setToolTip(f"{price:.2f} USD")
if __name__ == "__main__":
import sys
app = QApplication(sys.argv)
if not QSystemTrayIcon.isSystemTrayAvailable():
QMessageBox.critical(
None, "Systray", "I couldn't detect any system tray on this system."
)
sys.exit(1)
QApplication.setQuitOnLastWindowClosed(False)
trayIcon = SystemTrayIcon(parent=app)
trayIcon.show()
sys.exit(app.exec_())
推荐阅读
- performance - 将 20k 产品加载到 Opencart Journal Theme(版本 3.x)后,网站速度非常慢
- java - 简单计算器:加法错误输出
- c# - 控制台与 WebAPI 中共享类库的 MediatR 设置
- git - 如何向 .gitignore 添加内容?
- android - Flutter Launcher 图标没有改变?
- javascript - 它没有在控制台屏幕上显示任何输出。可能是什么问题
- python - Django DateTimeField 说“你比服务器时间提前 5.5 小时。”
- javascript - 从 javascript 客户端发送从 xmpp 协议收到的通知确认
- javascript - 在 REACT 兄弟组件之间传递数据
- android - 无法实例化 appComponentFactory