How to move GUI update to another QThread

493 views Asked by At

The code below creates a single QTableView window with 10,000 rows. Every second the view refreshes itself by calling the same update() function. Unfortunately this update process makes the entire window lock and slows down the responsiveness of the window noticeably.

I wonder if there is a way to move the call to update() function to another Thread so it does not block the main window?

enter image description here

from PyQt4 import QtCore, QtGui
app=QtGui.QApplication([])
items  = ['item_%04d'%i for i in range(10000)]

def update():
    view.model().sourceModel().clear()

    for i, item in enumerate(items):
        for column_number in range(5):
            item = QtGui.QStandardItem(item)
            model.setItem(i, column_number, item)


view = QtGui.QTableView()
model = QtGui.QStandardItemModel(len(items), 5)
proxy = QtGui.QSortFilterProxyModel()
proxy.setSourceModel(model)
view.setModel(proxy)

timer = QtCore.QTimer()
view.connect(timer, QtCore.SIGNAL("timeout()"), update)
timer.start(1000)

view.show()
app.exec_()

EDITED LATER:

The code below is my attempt to move the update GUI process to another thread. But unfortunately the lag is still there even while the update process happens in another thread (logging prints out the thread name):

enter image description here

from PyQt4 import QtCore, QtGui
import threading, time, logging  
logging.basicConfig(format='%(threadName)s:%(message)s', level=logging.DEBUG)

app=QtGui.QApplication([])
items  = ['item_%04d'%i for i in range(10000)]

def worker():   
    while True:
        view.model().sourceModel().clear()
        for i, item in enumerate(items):
            for column_number in range(5):
                item = QtGui.QStandardItem(item)
                model.setItem(i, column_number, item)

        time.sleep(1)       
        logging.info('updaing gui...')

view = QtGui.QTableView()
model = QtGui.QStandardItemModel(len(items), 5)
proxy = QtGui.QSortFilterProxyModel()
proxy.setSourceModel(model)
view.setModel(proxy)

t = threading.Thread(target=worker)
t.setDaemon(True)
logging.info('starting worker...')
t.start()
view.show()
app.exec_()
0

There are 0 answers