【发布时间】:2018-06-19 19:11:08
【问题描述】:
我有一个基本的信号/槽代码,我想在一个小部件中发出信号,然后在另一个小部件中连接该信号。
#!/usr/bin/python3
# -*- coding: utf-8 -*-
from PyQt5.QtWidgets import QMainWindow, QAction, QApplication, QWidget, QPushButton, qApp, QLabel, QHBoxLayout, QVBoxLayout, QSplitter, QFileDialog
from PyQt5.QtGui import QIcon, QPixmap, QPainter, QImage
from PyQt5.QtCore import QSize, Qt, pyqtSignal, QObject
import sys, random
import qdarkstyle
from os import path
class SignalFactory(QObject):
selectedTextureToLoad = pyqtSignal()
class Application(QMainWindow):
def __init__(self):
super().__init__()
self.signals = SignalFactory()
self.mainArea = MainArea()
# Option 1 - Uncomment below / Works but strong coupling between widgets
# self.signals.selectedTextureToLoad.connect(self.mainArea.doSomeStuff)
self.setCentralWidget(self.mainArea)
self.setGeometry(300, 300, 800, 400)
self.show()
def emitStuff(self):
print("Emitting...")
self.signals.selectedTextureToLoad.emit()
class MainArea(QWidget):
def __init__(self):
super().__init__()
self.signals = SignalFactory()
# Option 2 - Uncomment below / Does not work
#self.signals.selectedTextureToLoad.connect(self.doSomeStuff)
def doSomeStuff(self):
print("Receiving...")
if __name__ == '__main__':
app = QApplication(sys.argv)
ex = Application()
ex.emitStuff()
sys.exit(app.exec_())
如果我取消选项 1 的注释,则代码有效,并且接收到信号。但是,这两个小部件之间存在耦合。在这种情况下,这很好,因为一个小部件是另一个小部件的父级,并且自然会跟踪其子级。但在更复杂的场景中,这意味着跟踪许多小部件只是为了配置信号,这不是很好。
如果我取消注释选项 2,代码将不起作用,并且控制台仅显示“Emitting...”。这有点烦人,因为在我看来,这是在一个地方配置信号并从另一个地方发出信号的最干净的方式,而不会引入耦合。
我在这里缺少一些基本的东西吗?
编辑:
如果你像这样修改代码,通过添加returnASignal函数
from PyQt5.QtWidgets import QMainWindow, QAction, QApplication, QWidget, QPushButton, qApp, QLabel, QHBoxLayout, QVBoxLayout, QSplitter, QFileDialog
from PyQt5.QtGui import QIcon, QPixmap, QPainter, QImage
from PyQt5.QtCore import QSize, Qt, pyqtSignal, QObject
import sys, random
import qdarkstyle
from os import path
def returnASignal():
print('Returning a signal')
return pyqtSignal()
class SignalFactory(QObject):
selectedTextureToLoad = returnASignal()
class Application(QMainWindow):
def __init__(self):
super().__init__()
self.signals = SignalFactory()
self.mainArea = MainArea()
# Option 2 - Uncomment below / Works but strong coupling between widgets
# self.signals.selectedTextureToLoad.connect(self.mainArea.doSomeStuff)
self.setCentralWidget(self.mainArea)
self.setGeometry(300, 300, 800, 400)
self.show()
def emitStuff(self):
print("Emitting...")
self.signals.selectedTextureToLoad.emit()
class MainArea(QWidget):
def __init__(self):
super().__init__()
self.signals = SignalFactory()
# Option 1 - Uncomment below / Does not work
self.signals.selectedTextureToLoad.connect(self.doSomeStuff)
def doSomeStuff(self):
print("Receiving...")
if __name__ == '__main__':
app = QApplication(sys.argv)
ex = Application()
ex.emitStuff()
sys.exit(app.exec_())
运行时控制台显示如下:
Returning a signal
Emitting...
“Returning a signal”只打印一次而不是两次,这表明虽然有多个SignalFactory实例,但它们都共享同一个selectedTextureToLoad对象。这绝对是正确的static class member,而不是实例变量。所以,信号对象到处都是一样的,我还是不明白为什么选项2不起作用。
【问题讨论】:
-
我想你一直在说哪个有效,选项 1 无效而另一个有效。
-
您说得对,感谢您的关注;让我编辑代码来解决这个问题
标签: python pyqt pyqt5 signals-slots