Seb*_*ner 5 python parameters pyqt signals-slots pyside
我想要一个 pyqt 信号,它可以使用 python“object”子类参数或 None 发出。例如,我可以这样做:
valueChanged = pyqtSignal([MyClass], ['QString'])
Run Code Online (Sandbox Code Playgroud)
但不是这个:
valueChanged = pyqtSignal([MyClass], ['None'])
TypeError: C++ type 'None' is not supported as a pyqtSignal() type argument type
Run Code Online (Sandbox Code Playgroud)
或这个:
valueChanged = pyqtSignal([MyClass], [])
TypeError: signal valueChanged[MyObject] has 1 argument(s) but 0 provided
Run Code Online (Sandbox Code Playgroud)
我还尝试了 None 不带引号和 C++ 等效的“NULL”。但似乎两者都不起作用。我需要做什么才能使这项工作成功?
解决这个问题的一个技巧是定义要发出的信号object。因为None和MyClass都继承自它,object它按预期工作。这不需要在槽中进行铸造。
在 PyQt5 5.11.3 和 Python 3.5.6 中工作
信号
valueChanged = QtCore.pyqtSignal(object)
valueChanged.emit(MyClass())
valueChanged.emit(None)
Run Code Online (Sandbox Code Playgroud)
投币口
valueChanged.connect(slot)
def slot(my_class_instance):
if my_class_instance:
my_class_instance.some_method()
else:
# my_class_instance is None
Run Code Online (Sandbox Code Playgroud)
太长了;这个问题没有真正的解决方案。PyQtNone在定义信号重载时以特殊方式进行处理,因此最简单的解决方案是使用object它。有关具体原因的解释,请参见下文。
您尝试的方法不起作用有几个原因。
首先, 的type参数pyqtSignal接受 python类型对象或给出 C++ 对象(即 Qt 类)名称的字符串。字符串不能用于指定 python 类型 - 并且在任何情况下,None它是一个值,而不是类型。
其次,NonePyQt 进行了特殊处理,允许使用信号的默认重载,而无需显式选择签名。所以,即使type(None)在定义信号重载时使用,仍然不能解决问题。
(事后看来,PyQt 似乎更好的设计选择是使用内部哨兵对象作为默认值,而不是特殊情况None。但是,现在更改它可能为时已晚。PyQt5 和中的行为保持不变PyQt6 [截至 2023 年 3 月 13 日])。
为了更清楚地说明这一点,这里有一些示例代码:
class MyClass: pass
class X(QtCore.QObject):
valueChanged = QtCore.pyqtSignal([MyClass], [type(None)])
x = X()
x.valueChanged.connect(
lambda *a: print('valueChanged[]:', a))
x.valueChanged[MyClass].connect(
lambda *a: print('valueChanged[MyClass]:', a))
x.valueChanged[type(None)].connect(
lambda *a: print('valueChanged[type(None)]:', a))
print('emit: valueChanged[]')
x.valueChanged.emit(MyClass())
print('\nemit: valueChanged[type(None)]')
x.valueChanged[type(None)].emit(MyClass())
print('\nemit: valueChanged[MyClass]')
x.valueChanged[MyClass].emit(MyClass())
Run Code Online (Sandbox Code Playgroud)
输出:
class MyClass: pass
class X(QtCore.QObject):
valueChanged = QtCore.pyqtSignal([MyClass], [type(None)])
x = X()
x.valueChanged.connect(
lambda *a: print('valueChanged[]:', a))
x.valueChanged[MyClass].connect(
lambda *a: print('valueChanged[MyClass]:', a))
x.valueChanged[type(None)].connect(
lambda *a: print('valueChanged[type(None)]:', a))
print('emit: valueChanged[]')
x.valueChanged.emit(MyClass())
print('\nemit: valueChanged[type(None)]')
x.valueChanged[type(None)].emit(MyClass())
print('\nemit: valueChanged[MyClass]')
x.valueChanged[MyClass].emit(MyClass())
Run Code Online (Sandbox Code Playgroud)
正如您所看到的,当被用作重载时,除了默认重载(即参数列表中指定的第一个重载)type(None)之外,不可能选择任何其他内容。所有三个的行为方式完全相同,因为它们都选择相同的重载。MyClass
这也意味着尝试发出None将会失败,因为该值永远无法匹配所选重载的类型(默认为MyClass)。
一个简单的解决方法是使用object-type(None)但这样做的缺点是允许传递任何值。因此,如果保留类型很重要,另一种可能的解决方案可能是定义您自己的单例哨兵类来代替None.
| 归档时间: |
|
| 查看次数: |
12342 次 |
| 最近记录: |