如何通过工作线程更改进度

发布于 2024-12-14 19:50:45 字数 2522 浏览 1 评论 0原文

我是 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”线程之外​​更改 QPixmap。我不知道如何解决这个问题,所以我欢迎所有解决建议。

提前致谢。

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.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

离去的眼神 2024-12-21 19:50:45

不要尝试从线程内更新进度条:而是使用信号。

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

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_())
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文