Tjips
Tjips

Reputation: 13

How do I update my PyQt5 icon every 60 seconds?

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

Answers (1)

eyllanesc
eyllanesc

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

Related Questions