PyQt进度条线程更新

2024-06-28 19:29:07 发布

您现在位置:Python中文网/ 问答频道 /正文

我一直在写一个在服务器上运行远程脚本的程序。所以,我需要用一个条来显示进度,但不知怎么的,当我运行代码时,GUI开始冻结。我使用了QThread和SIGNAL,但不幸的是无法成功。

下面是我的代码

class dumpThread(QThread):

    def __init__(self):
        QThread.__init__(self)

    def __del__(self):
        self.wait()

    def sendEstablismentCommands(self, connection):

        # Commands are sending sequently with proper delay-timers #

        connection.sendShell("telnet localhost 21000")
        time.sleep(0.5)
        connection.sendShell("admin")
        time.sleep(0.5)
        connection.sendShell("admin")
        time.sleep(0.5)
        connection.sendShell("cd imdb")
        time.sleep(0.5)
        connection.sendShell("dump subscriber")

        command = input('$ ')

    def run(self):
        # your logic here              
        # self.emit(QtCore.SIGNAL('THREAD_VALUE'), maxVal)
        self.sendEstablismentCommands(connection)    

class progressThread(QThread):

    def __init__(self):
        QThread.__init__(self)

    def __del__(self):
        self.wait()


    def run(self):
        # your logic here
        while 1:      
            maxVal = 100
            self.emit(SIGNAL('PROGRESS'), maxVal)

class Main(QtGui.QMainWindow):
    def __init__(self):
        QtGui.QMainWindow.__init__(self)
        self.ui = Ui_MainWindow()
        self.ui.setupUi(self)
        self.ui.connectButton.clicked.connect(self.connectToSESM)



    def connectToSESM(self):
        ## Function called when pressing connect button, input are being taken from edit boxes. ##
        ## dumpThread() method has been designed for working thread seperate from GUI. ##

        # Connection data are taken from "Edit Boxes"
        # username has been set as hardcoded

        ### Values Should Be Defined As Global ###
        username = "ntappadm"
        password = self.ui.passwordEdit.text()
        ipAddress = self.ui.ipEdit.text()

        # Connection has been established through paramiko shell library
        global connection

        connection = pr.ssh(ipAddress, username, password)
        connection.openShell()
        pyqtRemoveInputHook()  # For remove unnecessary items from console

        global get_thread

        get_thread = dumpThread() # Run thread - Dump Subscriber
        self.progress_thread = progressThread()

        self.progress_thread.start()
        self.connect(self.progress_thread, SIGNAL('PROGRESS'), self.updateProgressBar)

        get_thread.start()     




    def updateProgressBar(self, maxVal):

        for i in range(maxVal):
            self.ui.progressBar.setValue(self.ui.progressBar.value() + 1)
            time.sleep(1)
            maxVal = maxVal - 1

            if maxVal == 0:
                self.ui.progressBar.setValue(100)

    def parseSubscriberList(self):
        parsing = reParser()

    def done(self):
        QtGui.QMessageBox.information(self, "Done!", "Done fetching posts!")




if __name__ == "__main__":
    app = QtGui.QApplication(sys.argv)
    main = Main()
    main.show()
    sys.exit(app.exec_())

我希望看到updateProgressBar方法已使用信号调用,所以进程将通过单独的线程。我找不到我失踪的地方。

谢谢你的帮助


Tags: fromselfuisignaltimeinitdefsleep
1条回答
网友
1楼 · 发布于 2024-06-28 19:29:07

有两个问题。我注意到的一件事是,如果Python线程不用于IO操作(比如从串行端口读取),那么它们是贪婪的。如果告诉线程运行计算或与IO无关的操作,则线程将占用所有处理,并且不希望让主线程/事件循环运行。第二个问题是信号很慢。。。非常慢。我注意到,如果你从一个线程发出一个信号并且做得非常快,它会大大减慢程序的速度。

所以问题的核心是,线程占用了所有的时间,而你发出的信号非常快,这将导致减速。

为了清晰和易于使用,我会使用新的风格的信号和插槽。 http://pyqt.sourceforge.net/Docs/PyQt4/new_style_signals_slots.html

class progressThread(QThread):

    progress_update = QtCore.Signal(int) # or pyqtSignal(int)

    def __init__(self):
        QThread.__init__(self)

    def __del__(self):
        self.wait()


    def run(self):
        # your logic here
        while 1:      
            maxVal = 100
            self.progress_update.emit(maxVal) # self.emit(SIGNAL('PROGRESS'), maxVal)
            # Tell the thread to sleep for 1 second and let other things run
            time.sleep(1)

连接到新样式信号

...
self.progress_thread.start()
self.process_thread.progress_update.connect(self.updateProgressBar) # self.connect(self.progress_thread, SIGNAL('PROGRESS'), self.updateProgressBar)
...

编辑 抱歉,还有一个问题。当一个信号调用一个函数时,你不能永远留在那个函数中。该函数没有在单独的线程中运行,而是在主事件循环上运行,主事件循环等待运行,直到您退出该函数。

更新进度休眠1秒并保持循环。绞刑是因为在这个函数中停留。

def updateProgressBar(self, maxVal):

    for i in range(maxVal):
        self.ui.progressBar.setValue(self.ui.progressBar.value() + 1)
        time.sleep(1)
        maxVal = maxVal - 1

        if maxVal == 0:
            self.ui.progressBar.setValue(100)

最好像这样写进度条

class progressThread(QThread):

    progress_update = QtCore.Signal(int) # or pyqtSignal(int)

    def __init__(self):
        QThread.__init__(self)

    def __del__(self):
        self.wait()


    def run(self):
        # your logic here
        while 1:      
            maxVal = 1 # NOTE THIS CHANGED to 1 since updateProgressBar was updating the value by 1 every time
            self.progress_update.emit(maxVal) # self.emit(SIGNAL('PROGRESS'), maxVal)
            # Tell the thread to sleep for 1 second and let other things run
            time.sleep(1)


def updateProgressBar(self, maxVal):
    self.ui.progressBar.setValue(self.ui.progressBar.value() + maxVal)
    if maxVal == 0:
        self.ui.progressBar.setValue(100)

相关问题 更多 >