I am writing a simple program that reads new input being written to a file and displays it in popup windows.
I am using PyQt5 for:
A) File changes (QtCore)
B) Window (QtWidgets)
Note that I do actually have a working model using signals as per PyQt reference guide. But couldn't figured out the below, therefore I am not understanding how things works.
While testing implementations i came across with multi-thread issues. This is a simplified example of my problem:
from PyQt5 import QtWidgets
import sys
import threading
def additem(window):
""" generates label in window at bottom """
print("Adding label to window on thread {}".format(threading.currentThread()))
row = window.layout().rowCount() + 1
btn = QtWidgets.QPushButton('button_' + str(row), window)
window.layout().addWidget(btn,row,1)
if __name__ == "__main__":
app = QtWidgets.QApplication(sys.argv)
w = QtWidgets.QWidget()
w.setLayout(QtWidgets.QGridLayout())
# set to timers after 3,6 will generate label in window
threading.Timer(3,additem,args=(w,)).start()
threading.Timer(6,additem,args=(w,)).start()
w.show()
sys.exit(app.exec_())
Output:
Adding label to window
QObject::setParent: Cannot set parent, new parent is in different thread
I tried setting global queue to pass around objects but still same error.
Although I now why the exception is raised, I do not understand how to avoid it.
One attempt was to directly pass the top object "app" and then getting the window by index (app is the top parent):
...
threading.Timer(3,additem,args=(app,)).start()
...
def additem(app):
w = app.allWidgets()[0]
...
I know PyQt is a C library wrapped in python but I am not familiar with C. The app object is a pointer to the object in the memory heap,
why it can't manipulate the object?
is the object being copied in a new thread? (thought I could still "update" that object)