I have the following simple code, and for some reason addItem() does not add an item to the List Widget in the app's UI in the exec_all() function. add_item() works perfectly fine outside of that function. Ive added the smallest snippet of the relevant code below:
from PyQt5 import QtWidgets, uic
from time import sleep
app = QtWidgets.QApplication([])
dlg = uic.loadUi("Program.ui")
def exec_all():
dlg.OutputConsole.addItem("Test")
web_scrap()
# etc...
# web_scrap(): A function in another file that
# scraps data from website. It needs to wait for
# HTML elements to fully load into DOM at times
# by using time.sleep()
def web_scrap(dlg):
sleep(5)
dlg.RunAllButton.clicked.connect(exec_all)
dlg.show()
app.exec()
UPDATE: Ive discovered where the problem lies by updating code snippet above to reproduce the problem -- it seems like addItem() does not want to execute before sleep() is called later, which is very odd to me unless addItem() is an asynchronous function? Will i have to use another method other than sleep() in web_scrap() in order to get around this problem?
sleep()or while/for loops are blocking, meaning that they prevent the event loop to properly process events, including requests for updates (aka: redraw widgets when required). If you add aprint(dlg.OutputConsole.count())afteraddItem()you'll see that it will properly print the correct element count of the list widget. Note that using an arbitrary time to wait for another "process" to end is a terrible idea: on a fast computer, you'll be waiting too much, on a slow one it will resume while the process hasn't completed yet.threadingmodule will suffice, but for short operations you may even consider callingQApplication.processEvents(). If you instead do need to interact with the UI (for example, to notify a finished "job"), you must use Qt signals/slots, because UI elements are not thread-safe; this means using QThread (either by subclassing, or to manage a QObject "worker" subclass) or eventually a QRunnable with a QObject "proxy" to emit signals.