问题
I'm new to PyQt4 so maybe it is a bagatelle. I try to show a progress in my GUI, which will be updated by an worker thread.The QProgressBar is with other memory's in a QTableWidget.
The worker thread starts in the init function of my GUI.
self.st = ServerThread()
self.st.start()
Here is the thread class
_exportedMethods = {
'changes': signal_when_changes,
}
class ServerThread(QtCore.QThread):
def __init__(self):
super(ServerThread,self).__init__()
st = self
#threading.Thread.__init__(self)
def run(self):
HOST = '' # local host
PORT = 50000
SERVER_ADDRESS = HOST, PORT
# set up server socket
s = socket.socket()
s.bind(SERVER_ADDRESS)
s.listen(1)
while True:
conn, addr = s.accept()
connFile = conn.makefile()
name = cPickle.load(connFile)
args = cPickle.load(connFile)
kwargs = cPickle.load(connFile)
res = _exportedMethods[name](*args,**kwargs)
cPickle.dump(res,connFile) ; connFile.flush()
conn.close()
If my Server changes values in the database he will call the following method which will captured with a remote prozedure call in the thread.
def signal_when_changes():
s = Subject()
s.advise()
The pattern is a simple observer, which updated my GUI. To update the table in my gui is the following method called.
def refresh(self,table):
clients = self.db.get_clients()
if(self.ui.mainTable.rowCount() != len(clients)):
self.search_add_client
allRows = table.rowCount()
for row in xrange(0,allRows):
for c in clients:
if table.item(row,0).text() == c.get_macaddr().text():
self.refresh_line(table,row,c)
This method checks wheter there were changes in a row if the needs a update the following method will do this.
def refresh_line(self,table,rowNumber,client):
table.item(rowNumber, 0).setText(client.get_macaddr().text())
table.item(rowNumber, 1).setText(client.get_product().text())
table.item(rowNumber, 2).setText(client.get_site().text())
table.item(rowNumber, 3).setText(client.get_hostname().text())
table.item(rowNumber, 4).setText(client.get_priv_data().text())
table.cellWidget(rowNumber, 5).setValue(client.get_progress_value())
table.item(rowNumber, 6).setText(client.get_stage().text())
The other memory's can be updated but not the progress, here the line in which i want to update the progress
self.ui.mainTable.setCellWidget(appendRowIndex,5,c.get_progress())
After this line the GUI crashes and i get the following message
QPixmap: It is not safe to use pixmaps outside the GUI thread
My conjecture is that i can't change QPixmaps outside the "Main/Gui" thread. I don't know how i can solve this problem, so I welcome all suggestions for resolution.
Thanks in advance.
回答1:
Don't try to update the progress bar from within the thread: use a signal instead.
from PyQt4 import QtCore, QtGui
class Thread(QtCore.QThread):
def __init__(self,parent):
QtCore.QThread.__init__(self, parent)
def run (self):
for step in range(5):
self.sleep(1)
self.emit(QtCore.SIGNAL('taskUpdated'))
class Window(QtGui.QWidget):
def __init__(self):
QtGui.QWidget.__init__(self)
self.button = QtGui.QPushButton('Start', self)
self.progress = QtGui.QProgressBar(self)
layout = QtGui.QVBoxLayout(self)
layout.addWidget(self.button)
layout.addWidget(self.progress)
self.connect(self.button, QtCore.SIGNAL('clicked()'),
self.handleButton)
self.thread = Thread(self)
self.connect(self.thread, QtCore.SIGNAL('taskUpdated'),
self.handleTaskUpdated)
def handleButton(self):
self.progress.setRange(0, 4)
self.progress.setValue(0)
self.thread.quit()
self.thread.start()
def handleTaskUpdated(self):
self.progress.setValue(self.progress.value() + 1)
def closeEvent(self, event):
self.thread.wait()
if __name__ == "__main__":
import sys
app = QtGui.QApplication(sys.argv)
window = Window()
window.show()
sys.exit(app.exec_())
来源:https://stackoverflow.com/questions/8076073/howto-change-progress-by-worker-thread