1

I coded a GUI with PyQt5 and I wanna update a quote from a website every day and update this quote in the GUI.

This is my main where I make the request to the website:

if __name__ == "__main__":


    app = QApplication(sys.argv)
    screen_res = app.desktop().screenGeometry()
    height = screen_res.height()
    width = screen_res.width()

    result = requests.get('https://somepage.com')
    page = result.text
    soup = BeautifulSoup(page, 'html.parser')
    quote = soup.find('div', class_ = 'quote').text

    quote = quote.replace(".", ". ")

    window = MainWindow(width, height, quote)


    sys.exit(app.exec_())

and that the GUI:

class MainWindow(QMainWindow):

    def __init__(self, width, height, quote, *args,**kwargs):
        
        
        
        super(MainWindow, self).__init__(*args, **kwargs)

        self.initUI(width, height, quote)
        print('successfully built initUI...')
        timer = QTimer(self)
        timer.timeout.connect(self.showlcd)
        timer.start(1000)
        self.showlcd()
        self.showDate()
        print('successfully showed lcd...')

        
    def initUI(self, width, height, quote):
        self.lcd = QLCDNumber(self)
        self.lcdDate = QLCDNumber(self)
        self.lcd.setDigitCount(8)
        self.lcdDate.setDigitCount(10)
        
        self.label = QLabel(self)
        self.label.setText(verse)
        self.label.setFont(QFont('Times', 70, QFont.Bold))
        self.label.setAlignment(Qt.AlignCenter)
        self.label.setWordWrap(True)
        

        

        self.setGeometry(0,0,width,height)

        layout = QVBoxLayout()
        layout.addWidget(self.lcd)
        layout.addWidget(self.lcdDate)
        layout.addWidget(self.label)

        widget = QWidget()
        widget.setLayout(layout)

        self.setCentralWidget(widget)
        
        self.show()


    def showlcd(self):
        time = QTime.currentTime()
        text = time.toString('hh:mm:ss')
        self.lcd.display(text)

    def showDate(self):
        """
        date = QDate.currentDate()
        textDate = date.toString(format = Qt.ISODate)
        self.lcdDate.display(textDate)
        """
        date = QDate.currentDate()
        date.toString(Qt.ISODate)
        final = date.toString('dd.MM.yyyy')

        self.lcdDate.display(final)

How can I make a loop which makes a new request at midnight and gives me the new quote?

Something like this:

while True: 
    getcurrentTime
    if getcurrentTime == midnight:
        make_new_request
        update_quote_str
        send_to_gui
        break

My problem is how can I loop when the gui is already running? And then somehow send a signal to the gui

1 Answers1

2

The logic is not to use a while True but a timer that fires every T seconds and checks if it is the time to get the "quote".

To simplify the task I have used the schedule library together with the QTimer, in addition the task of obtaining the "quote" is very time consuming so it can block the GUI so it must be executed in another thread, and finally you must create a method that updates the GUI without creating a new window.

import sys
import threading

import BeautifulSoup
import requests
import schedule

from PyQt5 import QtCore, QtGui, QtWidgets


class Crawler(QtCore.QObject):
    quoteChanged = QtCore.pyqtSignal(str)

    def start(self):
        threading.Thread(target=self._execute, daemon=True).start()

    def _execute(self):
        result = requests.get("https://somepage.com")
        page = result.text
        soup = BeautifulSoup(page, "html.parser")
        quote = soup.find("div", class_="quote").text
        quote = quote.replace(".", ". ")
        self.quoteChanged.emit(quote)


class MainWindow(QtWidgets.QMainWindow):
    def __init__(self, parent=None):
        super(MainWindow, self).__init__(parent)

        self.initUI()

        timer = QtCore.QTimer(self)
        timer.timeout.connect(self.showlcd)
        timer.start(1000)

        self.showlcd()
        self.showDate()

    def initUI(self):
        self.lcd = QtWidgets.QLCDNumber(digitCount=8)
        self.lcdDate = QtWidgets.QLCDNumber(digitCount=8)

        self.label = QtWidgets.QLabel(alignment=QtCore.Qt.AlignCenter, wordWrap=True)
        self.label.setFont(QtGui.QFont("Times", 70, QtGui.QFont.Bold))

        layout = QtWidgets.QVBoxLayout()
        layout.addWidget(self.lcd)
        layout.addWidget(self.lcdDate)
        layout.addWidget(self.label)

        widget = QtWidgets.QWidget()
        widget.setLayout(layout)
        self.setCentralWidget(widget)

    def set_quote(self, quote):
        self.label.setText(quote)

    def showlcd(self):
        time = QtCore.QTime.currentTime()
        text = time.toString("hh:mm:ss")
        self.lcd.display(text)

    def showDate(self):
        date = QtCore.QDate.currentDate()
        date.toString(QtCore.Qt.ISODate)
        final = date.toString("dd.MM.yyyy")
        self.lcdDate.display(final)


def main():

    app = QtWidgets.QApplication(sys.argv)

    w = MainWindow()

    crawler = Crawler()
    crawler.quoteChanged.connect(w.set_quote)

    schedule.every().day.at("00:00").do(crawler.start)

    dt = 1000
    schedule_timer = QtCore.QTimer(interval=dt, timeout=schedule.run_pending)
    schedule_timer.start()
    schedule.run_pending()

    w.showMaximized()

    app.exec_()


if __name__ == "__main__":
    main()
eyllanesc
  • 235,170
  • 19
  • 170
  • 241