首先,我是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_())
答案 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)
您正在将超时信号连接到None
(doWork()
方法的返回值),我认为这就是它只执行一次的原因:在连接期间调用doWork
不再。当你建立连接时,记得连接函数名称(用Pythonics字样,可调用对象)而不是函数调用。
顺便说一下,即使上面的问题解决了你的问题,你也应该避免使用线程,因为QTimer已经由你自己需要了。在docs you linked中,的第一个答案何时不应该使用线程?问题是:定时器。