Как изменить прогресс по рабочему потоку

Я новичок в PyQt4, так что, возможно, это пустяк. Я пытаюсь показать прогресс в своем графическом интерфейсе, который будет обновляться рабочим потоком. QProgressBar находится с другой памятью в QTableWidget.

Рабочий поток запускается в функции инициализации моего графического интерфейса.

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

Если мой сервер изменит значения в базе данных, он вызовет следующий метод, который будет захвачен удаленным вызовом процедуры в потоке.

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

Шаблон представляет собой простой наблюдатель, который обновил мой графический интерфейс. Для обновления таблицы в моем графическом интерфейсе вызывается следующий метод.

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

После этой строки происходит сбой графического интерфейса, и я получаю следующее сообщение

QPixmap: небезопасно использовать растровые изображения вне потока графического интерфейса.

Я предполагаю, что я не могу изменить QPixmaps вне потока «Main/Gui». Я не знаю, как я могу решить эту проблему, поэтому я приветствую все предложения по решению.

Заранее спасибо.


person Chris    schedule 10.11.2011    source источник
comment
я не знаю точно, но что-то вроде вызова метода или других может помочь вам, как только я столкнулся с этой проблемой с формами win как потокобезопасными,   -  person Red    schedule 10.11.2011


Ответы (1)


Не пытайтесь обновить индикатор выполнения из потока: вместо этого используйте сигнал.

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_())
person ekhumoro    schedule 10.11.2011
comment
Привет, сначала спасибо за ответ. Я использовал сигналы раньше, и я получил сообщение об ошибке, что основное приложение все еще работает... и мой код очень похож на ваш - person Chris; 11.11.2011
comment
@Крис. Дальнейшая помощь невозможна без просмотра полного сообщения об ошибке и/или кода, вызывающего проблему. - person ekhumoro; 11.11.2011
comment
Я извинился, на данный момент много стресса, я вернусь завтра, чтобы разобраться с проблемой, и тогда я смогу загрузить код-шеринг. - person Chris; 15.11.2011
comment
Можно ли использовать для заполнения QTableWidget из оператора базы данных? - person GSandro_Strongs; 16.10.2015
comment
@gs_developer_user3605534. Задайте новый вопрос — никто больше не увидит ваш комментарий. - person ekhumoro; 16.10.2015