如何在进入Qt事件循环后自动执行方法?
我想执行一个方法,这个方法只能在我的 QApplication
显示出来后才能调用,也就是说,只有在它进入主事件循环 exec_()
的时候才能执行。我刚开始接触 Qt4(使用 PyQt4):我希望能有一个类似 on_start()
的回调函数,但我没有找到这样的东西。
我需要创建一个线程或者定时器吗?还是说在这个 API 里已经有现成的回调可以用呢?
3 个回答
我之前没用过Qt,所以可能说得不太对,但我想你可以把你的 on_start()
方法和 ApplicationActivate
事件绑定在一起。这样的话,你可以在 on_start()
方法里设置一个标志,这样代码就只会在第一次运行的时候执行,而在程序运行过程中触发 ApplicationActivate
事件时就不会再执行了。
另一方面,如果 on_start()
方法是被多个线程调用的,你可能需要使用线程特定的标志。我自己没做过太多多线程的事情,所以不太清楚具体该怎么做,或者说这会有多简单或复杂。
你可以用一个一次性定时器来实现这个功能,就像下面这个简单的脚本:
import sys
from PyQt4 import QtGui, QtCore
app = QtGui.QApplication(sys.argv)
def on_start():
print(' in event loop!')
print(' telling app to exit ...')
app.exit(123)
QtCore.QTimer.singleShot(0, on_start)
print('About to enter event loop')
rc = app.exec_()
print('All done - returned %d' % rc)
当你运行这个脚本时,你应该能看到
About to enter event loop
in event loop!
telling app to exit ...
All done - returned 123
目前我选择用 QThread
这样来实现:
class MyThread(QtCore.QThread):
def run(self):
''' reinplemented from parent '''
# make thread sleep to make sure
# QApplication is running before doing something
self.sleep(2)
do_something()
class MyWidget(QtGui.QWidget):
def __init__(self, parent=None):
QtGui.QWidget.__init__(self, parent)
self.attr = 'foo'
self.thread = MyThread(self)
self.thread.start()
def main():
app = QtGui.QApplication(sys.argv)
w = MyWidget()
w.show()
sys.exit(app.exec_())
这样做对我来说是有效的,因为我在(真实的)代码中,线程实际上是在 X 显示中寻找应用程序窗口,并会一直尝试直到找到它。不过,这并不是解决问题的优雅方式。如果 QApplication
在进入事件循环时能发出一个信号,那就更好了。JAB 提出了 Qt.ApplicationActivate,但似乎 QApplication
并没有发出这个信号。即使它发出了,由于 MyWidget()
不是作为 QApplication
的子对象实例化的,我也不知道怎么把信号从 app
传递到 w
。
在接受我的答案作为最终解决方案之前,我会等一个更好的答案,如果有的话。