Reputation: 13
I am new to python and I am makeing a simple appliacation where the value of bitcoin is displayed in the system tray. I am useing PyQt5.
My question is: How do I refresh the value and icon every minute. When I try it my menu wont work anymore. Is there a simple fix?
This is my code:
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_())
Upvotes: 1
Views: 104
Reputation: 243993
Don't use while True, urlopen or time.sleep as they block the eventloop, instead use a QTimer with QNetworkAccessManager:
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_())
Upvotes: 3