进入Qt事件循环后如何自动执行方法?
Posted
技术标签:
【中文标题】进入Qt事件循环后如何自动执行方法?【英文标题】:How to execute a method automatically after entering Qt event loop? 【发布时间】:2011-06-02 14:11:12 【问题描述】:我想执行一个方法,该方法只能在我的QApplication
显示后调用,即当它进入其主事件循环exec_()
时。我是 Qt4 的新手(使用 PyQt4):我希望有一个类似 on_start()
的回调,但没有找到。
我需要创建线程或计时器吗?还是 API 中已经包含一些回调?
【问题讨论】:
【参考方案1】:您可以为此使用单次计时器,如以下简单脚本所示:
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
【讨论】:
谢谢,我也想过使用 QTimer。我最终选择了QThread,我认为它更易于使用。但是您的示例比文档更清楚:)【参考方案2】:我以前没有使用过 Qt,所以我可能错了,但我想你可以将你的 on_start()
方法绑定到 ApplicationActivate
事件,并从你的 on_start()
方法中设置一个标志,以便代码只会在第一次运行,而不会在其他任何时候在程序执行期间触发ApplicationActivate
事件。
另一方面,如果on_start()
方法将被多个线程调用,您可能希望使用特定于线程的标志。我自己没有做过太多的多线程,所以我不确定具体是什么,或者它有多简单/复杂。
【讨论】:
嘿,谢谢。我见过Qt.ApplicationActivate
,但我仍然感到困惑,因为QApplication
没有实现该信号。如果我必须将此信号绑定到QApplication
,它也必须在事件循环开始之后发生,这让我回到了最初的问题。但也许我只是不明白信号在 Qt 中是如何工作的 :)
“但我仍然感到困惑,因为 QApplication 没有实现该信号。”这就是子类化的目的。
@JAB:是的,我在我的评论和你的评论之间想到了这一点。但是QApplication
的事件是否可以传递给QWidget
,即使后者不是前者的孩子?我只见过最顶层小部件的子级之间的事件处理。
我认为这应该是可能的,但正如我所说,我没有任何实际使用 Qt 的经验。 riverbankcomputing.co.uk/static/Docs/PyQt4/html/…
@JAB:哈!也许我可以将Widget()
实例连接到 Widget() 类定义之外的QApplication
,即在main()
函数中。我会尝试让你知道它是如何工作的。谢谢。【参考方案3】:
现在我选择这样使用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
的信号
我会等待更好的答案(如果有的话),然后再接受我的答案作为选择的解决方案。
【讨论】:
以上是关于进入Qt事件循环后如何自动执行方法?的主要内容,如果未能解决你的问题,请参考以下文章
qt源码解析1--事件循环原理(重写事件函数,事件过滤器等)
WPF中想要让一个按钮单击事件结束后自动再单击这个按钮,也就是让单机事件连续反复执行,应该如何实现?