2011-11-10 21 views
3

我是PyQt4的新手,所以也許它是一個小手指。我嘗試在我的GUI中顯示進度,這將由工作線程更新。QProgressBar與QTableWidget中的其他內存有關。如何通過工作線程改變進度

工作線程在我的GUI的init函數中啓動。

self.st = ServerThread() 
    self.st.start() 

這裏是線程類

_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() 

如果我的服務器在他會叫下面的方法將與在線程遠程調用prozedure捕獲的數據庫變化值。

def signal_when_changes(): 
    s = Subject() 
    s.advise() 

該模式是一個簡單的觀察者,它更新了我的GUI。在我的gui中更新表格是調用以下方法。

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) 

如果需要更新,則此方法檢查是否有更改,如果需要更新,則以下方法將執行此操作。

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()) 

其他存儲的可更新,但沒有取得進展,在這裏,我要更新進度

self.ui.mainTable.setCellWidget(appendRowIndex,5,c.get_progress()) 

這條線之後,GUI崩潰,我得到以下信息行

的QPixmap:這是不是安全使用GUI線程之外的像素映射

我的猜想是我不能在「Main/Gui」線程之外​​更改QPixmaps。我不知道如何解決這個問題,所以我歡迎所有的解決方案。

在此先感謝。

+0

我天璣KNW準確,但類似的方法調用或其他人可能會幫助ü,一旦我得到了這個問題,贏形式線程安全的, – Red

回答

2

不要嘗試更新線程內的進度條:改爲使用信號。

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_()) 
+0

嘿,先謝謝大家的回答。我之前使用過信號,並收到「主應用程序仍在運行...」的錯誤消息,而且我的代碼看起來非常類似於您的 – Chris

+0

@Chris。如果沒有看到完整的錯誤信息和/或導致問題的代碼,就無法進一步提供幫助。 – ekhumoro

+0

我很抱歉現在有很多壓力我明天要回去處理這個問題,然後我可以上傳代碼共享 – Chris