pyqt信号和槽机制

转载自:简书 PyQt信号和槽机制
信号和槽(Signals and Slots)
程序员不在乎按钮何时按下,只关心按钮是否按下以便适当地做出反应。因此,Qt和PyQt提供了两种通信机制:底层事件处理机制,类似于所有其他GUI库提供的机制,以及Trolltech(Qt)的制造商所称的高级机制–“信号和槽”。
每个QObject,包括所有的PyQt的小部件,都是从QWidget(一个QObject的子类)派生,都支持信号和槽机制。特别的,他们能够通知状态的改变,例如当复选框被选中或未选中,或当按钮被点击等其他重要的事件。所有的PyQt小部件有一组预定义 的信号,例如点击按钮的clicked信号。
每当一个信号发射,默认情况下PyQt只是抛出它,而要注意到信号,就需要将其连接到槽。在C++/Qt中,槽是必须用特殊语法声明的方法;但在PyQt中,它可以是任意可调用的对象(例如任何函数或方法),并且在定义时不需要特殊的语法。
信号和槽的一般写法:

s.connect(w, SIGNAL("signalSignature"), functionname)
s.connect(w, SIGNAL("signalSignature"), instance.methodName)
s.connect(w, SIGNAL("signalSignature"), instance, SLOT("slotSignature"))

sinalSignature是信号的名称,以及括号中的逗号分隔的参数类型名称列表(可能为空)。如果信号是一个Qt信号,类型名称必须是C++类型名称,如int和QString。C++类型名称可能相当复杂,每个类型名称可能包括一个或多个const,*和&。当我们将它们写为信号(或槽)签名时,可以丢弃任何const和&,但必须保留*。例如Qstring对象的几乎每个Qt信号都是用const QString类型的参数,但在PyQt中,仅仅使用QString就足够;另一方面,QListWidget对象具有签名itemActivated(QListWidgetItem *)的信号,使用PyQt时必须写入与这个完全一样的信号。
几个signalSignature的样例: 按钮点击信号SIGNAL(“clicked()”);QTreeWidget对象的切换信号SIGNAL(“itemSelectionChanged()”); QTabWidget的切换页标签信号SIGNAL(“currentChanged(int)”)。其中括号中的参数,可以有多个,也可以为空。
slotSignature和signalSignature具有相同的形式,只是slotSignature必须是Qt的slot,不能是自定义的槽?(此处存疑,待验证)插槽的自变量数量可以少于连接到该插槽的信号数量,这样将会丢弃额外的参数。(意思信号可以传入未经槽函数定义的参数?)相应的信号和曹参数必须具有相同的类型,例如,不能将valueChanged(int)信号连接到setText(Qstring)槽。
当槽是一个Qt槽而不是一个Python方法时,使用SLOT()语句更高效,如将self.connect(spinbox, SIGNAL("valueChanged(int)", dial.setValue)改写为self.connect(spinbox, SIGNAL("valueChanged(int)", dial, SLOT("setValue(int)")会更高效。
可以将多个信号连接到同一个槽,也可以将单个信号连接到多个槽,也可以将信号连接到另一个信号。
连接使用QObject.connet(),打破使用QObject.disconnect()。实际中很少需要主动断开,因为PyQt会自动断开所有涉及被删除对象的连接。
到目前为止,我们已经看到了如何连接到信号,以及如何编写槽,它可以是普通的函数或方法。我们知道信号被发射以表示状态变化或其他重要事件。但是如果我们想创建一个发出自己信号的组件呢?这用QObject.emit()很容易实现。例如,一个完整的QSpinBox子类,发出自己的自定义atzero信号,并且还传递一个数字:

class ZeroSpinBox(QSpinBox):
	zeros = 0
	def __init__(self, parent=None):
		super(ZeroSpinBox, self).__init__(parent)
		self.connect(self, SIGNAL("valueChanged(int)"), self.checkzero)

	def checkzero(self):
		if self.value() == 0:
			self.zeros += 1
			slef.emit(SIGNAL("atzero"), self.zeros)

我们连接到SpinBox自己的valueChanged()信号,并将其调用自定义的checkzero()插槽。如果值恰好为0,则checkzero()槽发出零值信号,以及它已经为零的次数的计数。
可以看到SIGNAL(“atzero”)信号没有参数,表明这个一个短路信号,当为短路信号时,任何数据都可以作为附加参数传递给emit()方法,并且他们作为python对象传递。这避免了将参数转化为C++数据类型和从C++数据类型转换的开销,并且还意味着可以传递任何python对象,甚至可以时不能转化为C++数据类型的对象。具有至少一个自变量的信号是Qt信号或非短路信号。在这种情况下,PyQt会检查信号是否为Qt信号,如果不是,则会假定它是一个python信号,并且参数都将转化为C++数据类型。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值