PySide中的子线程中的计时器

时间:2012-03-25 17:08:00

标签: python qt pyside

首先,我是Python和Pyside的新手。为了做一些自我改进,我试图在我的PySide程序的子线程中每秒执行一次QTimer执行(此时我只想让它每秒钟打印一个终端“hi!”没有冻结主窗口。)

我尝试将example I found on the Qt Wiki从C ++转换为Python / PySide,但由于我不太了解C ++,我认为我错误地转换了它,这就是为什么它无法正常工作。

目前,doWork()函数似乎只执行一次,然后再也不会执行。我究竟做错了什么?有没有更好的方法在PySide中每秒执行一次函数而不冻结主窗口?

这是代码(我删除了一些主窗口代码以提高清晰度):

from PySide import QtGui
from PySide import QtCore
from client_gui import Ui_MainWindow

statsThread = QtCore.QThread()

class MainWindow(QtGui.QMainWindow, Ui_MainWindow):
    def __init__(self, parent=None):
        super(MainWindow, self).__init__(parent)
        #setup GUI
        self.setupUi(self)
        #start thread to update GUI
        self.statsThread = updateStatsThread()
        self.statsThread.start(QtCore.QThread.TimeCriticalPriority)

class updateGuiWithStats(QtCore.QObject):
    def Worker(self):
        timer = QtCore.QTimer()
        timer.timeout.connect(self.doWork())
        timer.start(1000)

    def doWork(self):
        print "hi!"

class updateStatsThread (QtCore.QThread):
    def run(self):
        updater = updateGuiWithStats()
        updater.Worker()
        self.exec_()

if __name__ == '__main__':
    app = QtGui.QApplication(sys.argv)
    frame = MainWindow()
    frame.show()
    sys.exit(app.exec_())

2 个答案:

答案 0 :(得分:4)

@Masci已经指出了您timer.timeout.connect所需的修复方法,但我看到的问题不仅仅是那个问题。

无需创建从未使用过的全局QThread:

statsThread = QtCore.QThread()

您的QTimer正在被垃圾收集,因为它是在没有父母的情况下创建的,并且您不会将其保存在您的班级中。这就是为什么即使你修复你的计时器连接后,它仍然无法正常工作...尝试:

class UpdateGuiWithStats(QtCore.QObject):

    def startWorker(self):
        self.timer = QtCore.QTimer()
        self.timer.timeout.connect(self.doWork)
        self.timer.start(1000)

另外,使用UpperCase作为类的第一个字母,使用camelCase作为方法。你正在做两种方式的混合。

基于您提供的链接,您的示例以及此处的其他评论的几个注释...如果您的doWork()非常轻且不会阻止您的主要内容,您可以仅使用QTimer作为解决方案事件循环与一堆数据运算,休眠等。如果确实如此,那么doWork()将需要移动到QThread,就像你的例子一样。但是在这一点上,在一个调用自己的工作的单独类中使用事件循环和QTimer是有点不必要的。这一切都可以合并为一个类,如:

class UpdateStatsThread(QtCore.QThread):

    def __init__(self, parent=None):
        super(UpdateStatsThread, self).__init__(parent)
        self._running = False

    def run(self):
        self._running = True
        while self._running:
            self.doWork()
            self.msleep(1000)

    def stop(self, wait=False):
        self._running = False
        if wait:
            self.wait()

    def doWork(self):
        print "hi!"

答案 1 :(得分:1)

updateGuiWithStats类中,Worker方法:

timer.timeout.connect(self.doWork())

应该是

timer.timeout.connect(self.doWork)

您正在将超时信号连接到NonedoWork()方法的返回值),我认为这就是它只执行一次的原因:在连接期间调用doWork不再。当你建立连接时,记得连接函数名称(用Pythonics字样,可调用对象)而不是函数调用。

顺便说一下,即使上面的问题解决了你的问题,你也应该避免使用线程,因为QTimer已经由你自己需要了。在docs you linked中,的第一个答案何时不应该使用线程?问题是:定时器。

相关问题