我正在学习PyQt(我之前没有使用过C ++ Qt。)
我不明白信号和插槽的原因。也就是说,我似乎可以通过直接调用类的方法来完成所有操作。这样做似乎更Pythonic,使用更少的代码,更容易阅读。我错过了什么?
为了澄清,我问为什么要这样做:
def mouseReleaseEvent(self):
self.clicksignal.connect(ui.iconClicked)
self.clicksignal.emit()
当我能做到这一点时:
def mouseReleaseEvent(self):
ui.iconClicked()
答案 0 :(得分:5)
存在信号和插槽的原因是因为除了UI线程之外,您无法从应用程序的任何其他线程更改GUI。
如果你要做一些繁重的CPU密集型计算,或任何等待IO或任何类似事情的任务......如果你这样做UI线程(例如,如果你获取一个url或持续一段时间的东西) ,你的UI线程将忙,GUI事件循环将无法自行更新,因此GUI似乎会被冻结。
进行这些操作。您在一个单独的(后台工作程序)线程中执行它们,因此UI线程可以继续更新GUI。
现在问题是您无法访问GUI的元素并从除UI线程之外的任何其他线程更改其状态。因此引入了信号和插槽。当您发出信号时,它确保被捕获在UI线程中,并且插槽将在UI线程中执行。
我不确定你在你的例子中想要完成什么,但这是信号和插槽存在的主要原因。基本上UI线程应该只处理UI,其他一切都应该在后台工作线程中完成,该线程发送一个在UI线程中捕获的信号,更新GUI的插槽在UI线程中执行。
答案 1 :(得分:3)
嗯......是的,你可以。但你需要更大的思考。在您的示例代码中,mouseReleaseEvent
的调用者必须具有对接收通知的对象的引用,并显式调用适当的方法。使用插槽&信号机制从事件消费者中解耦事件生成器(例如小部件) - 几乎任意的其他对象。这使得设置通信和控制流更容易,并且在低级UI组件外部,这是好事。它还使这些组件可以重复使用 - 通过在外部移动布线代码,我们使其独立于应用程序逻辑。
答案 2 :(得分:3)
除了@ViktorKerkez和@Wilbur的答案之外,信号和插槽还提供了火灾和遗忘的通知系统,以及解耦类。
这样做的一大优点是,一个班级可以发出信号,而不知道接收信息的内容是谁。它可能只是一个连接了插槽的对象,也可能是几十个。或者,您可能需要一个具有一个插槽的单个类,该插槽连接到多个信号。所以它可以用作通知系统。
例如,假设一个程序,其中许多不同类型的对象将信息发送到日志。对象只是发出一个Log(文本)信号,而不关心实际记录的内容。这些信号可以连接到日志类,可以记录到文件,网络,屏幕或一次全部。记录对象不关心。