![](/img/trans.png)
[英]PyQt5 Filebrowser Signal-Slot: connecting QTreeView to QColumnview
[英]PyQt5 signal-slot decorator example
我目前正在创建一个生成pyqtSignal(int)和pyqtSlot(int)的类。 困难在于创建发出特定值的信号。
假设我想生成类似于以下简单示例的内容:
import sys
from PyQt5.QtCore import (Qt, pyqtSignal, pyqtSlot)
from PyQt5.QtWidgets import (QWidget, QLCDNumber, QSlider,
QVBoxLayout, QApplication)
class Example(QWidget):
def __init__(self):
super().__init__()
self.initUI()
def printLabel(self, str):
print(str)
@pyqtSlot(int)
def on_sld_valueChanged(self, value):
self.lcd.display(value)
self.printLabel(value)
def initUI(self):
self.lcd = QLCDNumber(self)
self.sld = QSlider(Qt.Horizontal, self)
vbox = QVBoxLayout()
vbox.addWidget(self.lcd)
vbox.addWidget(self.sld)
self.setLayout(vbox)
self.sld.valueChanged.connect(self.on_sld_valueChanged)
self.setGeometry(300, 300, 250, 150)
self.setWindowTitle('Signal & slot')
self.show()
if __name__ == '__main__':
app = QApplication(sys.argv)
ex = Example()
sys.exit(app.exec_())
我对上述代码的第一个问题是:
pyqtSlot(int)
根本不使用pyqtSlot()装饰器对代码没有影响? 对于具体原因,我想生产使用pyqtSignal()工厂我自己的信号和我给出体面的文件在这里 。 然而,唯一的问题是,这个非常简单的例子没有为如何发出特定信号提供坚实的基础。
这是我想要做但却发现自己迷失了:
这就是我想要的:
from PyQt5.QtWidgets import QPushButton, QWidget
from PyQt5.QtCore import pyqtSignal, pyqtSlot
from PyQt5.QtWidgets import QSlider
def template(Q_Type, name: str, *args):
class MyWidget(Q_Type):
def __init__(self) -> None:
super().__init__(*args)
self._name = name
def setSignal(self,type):
self.signal = pyqtSignal(type)
def callSignal(self):
pass
return MyWidget
如你看到的。 我给小部件命名,因为我发现它很有用,我也尝试从类中实例化QWidget以简化代码。
这就是我希望主类从第一个例子中生成小部件的方法:
import sys
from PyQt5.QtCore import (Qt, pyqtSignal, pyqtSlot)
from PyQt5.QtWidgets import (QWidget, QLCDNumber, QSlider,
QVBoxLayout, QApplication)
class Example(QWidget):
def __init__(self):
super().__init__()
self.initUI()
def printLabel(self, str):
print(str)
@pyqtSlot(int)
def sld_valChanged(self, value):
self.lcd.display(value)
self.printLabel(value)
def initUI(self):
#instantiate the QWidgets through template class
self.lcd = template(QLCDNumber,'lcd_display')
self.sld = template(QSlider, 'slider', Qt.Horizontal)
#create signal
#self.sld.setSignal(int)
vbox = QVBoxLayout()
vbox.addWidget(self.lcd)
vbox.addWidget(self.sld)
self.setLayout(vbox)
#connect signal - this won't send the value of the slider
#self.sld.signal.connect(self.sld_valChanged)
self.sld.valueChanged.connect(self.sld_valChanged)
self.setGeometry(300, 300, 250, 150)
self.setWindowTitle('Signal & slot')
self.show()
if __name__ == '__main__':
app = QApplication(sys.argv)
ex = Example()
sys.exit(app.exec_())
这里只需解决两个问题:
Q_Type
告诉我它的类型是PyQt5.QtCore.pyqtWrapperType
,它应该是PyQt5.QtWidgets.QSlider
。 QSlider
发送我希望它发送的更改的值。 我相信这就是emit()
发挥作用但却没有足够的知识来了解它是如何有用的。 我知道如果我希望信号将值35传递给槽函数,我可以使用某种函数调用self.sld.emit(35)
。 问题不是如何,而是应该在哪里实现这个功能? 我可能完全偏离并过度思考解决方案,随意纠正我的代码,以便我可以让我的信号发出滑块的值。
为什么在删除pyqtSlot(int)时根本不使用pyqtSlot()装饰器对代码没有影响? 你能举例说明什么时候需要吗?
已经在您之前的问题中解决了,但我会再次重复。
虽然PyQt4允许任何Python可调用在连接信号时用作插槽,但有时需要将Python方法明确标记为Qt插槽并为其提供C ++签名。 PyQt4提供了pyqtSlot()函数装饰器来完成这项工作。
将信号连接到装饰的Python方法还具有减少内存使用量的优势,并且速度稍快。
此外,正如您在上一个问题中所述 , 您不能将信号创建为实例变量,它们必须是类属性 。
这永远不会奏效
def setSignal(self,type):
self.signal = pyqtSignal(type)
一定是
class MyWidget(QWidget):
signal = pyqtSignal(int)
创建一个元类,允许实现许多不同类型的QWidget子类。
您无法为QObjects
定义元类,因为它们已经使用了自己的元类(这是允许信号魔法工作的原因)。 但是,您仍然可以使用type
函数创建QObject
子类工厂。
def factory(QClass, cls_name, signal_type):
return type(cls_name, (QClass,), {'signal': pyqtSignal(signal_type)})
MySlider = factory(QSlider, 'MySlider', int)
self.sld = MySlider(Qt.Horizontal)
self.sld.signal.connect(self.on_signal)
让元类产生自己的信号,可以从课外调用。
总之,不要这样做。 你不应该从课外发出信号。 上面的工厂示例不是很有用,因为您没有在这些类上定义自定义方法来发出这些信号。 通常,这是您使用自定义信号的方式
class MyWidget(QWidget):
colorChanged = pyqtSignal()
def setColor(self, color):
self._color = color
self.colorChanged.emit()
class ParentWidget(QWidget):
def __init__(self):
...
self.my_widget = MyWidget(self)
self.my_widget.colorChanged.connect(self.on_colorChanged)
# This will cause the colorChanged signal to be emitted, calling on_colorChanged
self.my_widget.setColor(Qt.blue)
def on_colorChanged(self):
# do stuff
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.