[PyKDE] Updating GUI from another thread
Jeffrey Barish
jeff_barish at earthlink.net
Thu Apr 7 04:04:10 BST 2005
This problem seems to come up regularly, but I am wondering whether the
solution I found for my situation is safe. I have a program in which I
run a time-consuming task in its own thread. Every time the task
reaches a milestone, I want it to deselect a listbox item. In the test
program below, the GUI thread creates a listbox with 3 items. The user
can select one and then push the button. The object is to deselect the
selected item from another thread. I tried using a custom event. I
found that I need a timer in the GUI thread to trigger a processEvents
call. Then I discovered that I don't seem to need the custom event: I
can simply deselect the item from the task thread, although the
processEvents call is still necessary. Is the issue that something bad
could happen if I happen to try selecting the item at the same time the
task thread is trying to deselect it? Is the solution with the custom
event optimal? The timer seems inelegant. I had hoped to find a
solution where the thread could somehow order the GUI thread to
deselect and update.
# The purpose of this test is to explore the problem of deselecting a
# listbox item from another thread.
import sys
import thread
from qt import *
class MainWindow(QMainWindow):
def __init__(self, *args):
QMainWindow.__init__(self, *args)
self.mainWidget = QWidget(self)
self.setCentralWidget(self.mainWidget)
self.lb = QListBox(self.mainWidget)
self.button = QPushButton("Clear selections", self.mainWidget)
QObject.connect(self.button, SIGNAL('clicked()'),
self.clearSelections)
for i in range(3): QListBoxText(self.lb, "some text %d" % i)
self.vlayout = QVBoxLayout(self.mainWidget)
self.vlayout.addWidget(self.lb)
self.vlayout.addWidget(self.button)
self.timer = QTimer()
QObject.connect(self.timer, SIGNAL("timeout()"),
self.periodicCall)
self.timer.start(500)
def periodicCall(self):
app.processEvents()
def clearSelections(self):
thread.start_new_thread(self.do_clearSelections, ())
def customEvent(self, e):
if e.type() == 65432:
lbi = e.lbi
lb = e.lb
lb.setSelected(lbi, False)
def do_clearSelections(self):
lbi = self.lb.firstItem()
while lbi:
print "lbi.selected() =", lbi.selected()
if lbi.selected():
## e = MyEvent(self.lb, lbi)
## app.postEvent(self, e)
self.lb.setSelected(lbi, False)
lbi = lbi.next()
class MyEvent(QCustomEvent):
def __init__(self, lb, lbi):
QCustomEvent.__init__(self, 65432)
self.lb = lb
self.lbi = lbi
def lbi(self):
return self.lbi
app = None
def main(args):
global app
app = QApplication(args)
win = MainWindow()
app.setMainWidget(win)
win.show()
app.connect(app, SIGNAL("lastWindowClosed()"), app, SLOT("quit()"))
app.exec_loop()
if __name__ == "__main__":
main(sys.argv)
--
Jeffrey Barish
More information about the PyQt
mailing list