您的位置:首页 > 编程语言 > Qt开发

PyQt4的信号与插槽中简单实例源码讲解

2017-05-10 14:36 633 查看
#coding=utf8
'''
每个GUI库都提供有发生事件(event)的详细信息,例如鼠标点击、按键。
例如,如果有一个带有"Click Me"文本的按钮(button),用户点击该按钮,
各种信息都变成可用的。
GUI库能告诉用户用鼠标点击相关按钮、相关按钮父级widget、相关屏幕的位置。
GUI库能告诉用户Shift、Ctrl、Alt以及NumLock按键在点击时的状态、点击和释放的精确时间等等。
相似的情况,在没有使用鼠标,用户点击Button的详细信息也会被提供。
例如,用户按Tab键足够的时间来移动光标到button上,然后按Spacebar键;或者用户按Alt+C组合键。
虽然在这些情况下,结果是一样的,点击button的不同方式会产生不同的事件和不同的信息。

Qt库在首次几乎可以识别所有事例,程序员不需要或者不需要想所有低级别的details:
不用考虑按钮怎么被按下,仅仅需要知道按钮被按下能作出适当的响应。
由于这个原因,PyQt提供了两种交互机制:
1》一个低级别的事件处理机制,该机制与所有其他GUI库提供的类似
2》一个高级别的事件处理机制,该机制在Trolltech被称作“信号与插槽(Signals and slots)”

每个QObject(包括PyQt所有的widget)因为它们从QWidget派生,
一个QObject子类---支持"信号与插槽"机制。
尤其是,它们可以申明状态的改变,例如,当一个复选框(checkbox)变成可选(checked)或者不可选(unchecked)时;
和其他重要事件的发生,例如当一个按钮被点击时。

PyQt的所有widget都有一组预定义信号。无论何时发出信号,默认情况下PyQt会将其丢弃。
为了注意一个信号,必须把信号连接到widget的slot(插槽)。
在C++/QT里,slot是用特殊语法申明的方法,但是在PyQt中,
它们可以根据程序员意愿(例如,任何函数和方法)调用,
而且当定义slot时,不需要特别的语法。

大部分widget也需要预定义slot(插槽),所以在一些案例中,需要连接一个预定义信号到一个预定义slot中,
不必做任何事情,也能获得想要的行为操作(behavior)。
PyQt比C++/Qt在slot方面更多样化,因为不仅仅可以连接slot也能连接任何回调函数;
从PyQt4.2,可以动态添加"预定义(predefined)"信号和slot到QObject。

下面给出实例,讲解信号和slot是怎么工作的:
该实例是顶级是一个QDialog窗口,这个窗口包含一个QDial、QSpinBox、QHBoxLayout。
这两widget有valueChanged()信号,当信号被发送时,获取新的值。
它们都有以一个整数值为参数的setValue()插槽(slot).
因此,可以将这两个小部件彼此连接起来,以便用户改变其中的任何一个,都将将导致另一个做出相应的更改。
由于两个widget被相互连接,当用户移动环形范围调节器时,环形范围调节器将会发送一个valueChanged(int)
的信号.

connect函数:
s与w是QObject,通常都是widget,s通常是self
s.connect(w, SIGNAL("signalSignature"), functionName)
s.connect(w, SIGNAL("signalSignature"), instance.methodName)
s.connect(w, SIGNAL("signalSignature"),instance, SLOT("slotSignature"))

signalSignature是信号的名字和一个(可能是空的)逗号分隔括号中的参数类型名称列表。
如果信号是一个Qt信号,在C++类名中如int和QString。C++命名是很复杂的,在一个类型前面
可能包括一个或多个const,*,&。
当写一个C++变量作为信号或者插槽时,需要丢弃consts与&s,但必须保持*s。
例如,大多数Qt信号通过一个QString传递,该QSting是一个cosnt QString&类型参数;
在PyQt仅仅使用QString。在另一方面,QListWidget有一个itemActivated(QListWidgetItem*)的信号,
必须按照上面给出的格式写。
PyQt信号在实际发射时被定义,可以包含任意数量的参数,该参数可以是任何类型。

slotSignature和signalSignature格式类似,除了命名不一样是一个Qt slot。
一个slot(插槽)可能没有像信号在被连接时需要那么多的参数,甚至是更少;详细的参数被丢弃。
相关的信号和slot必须保持相同的参数类型,例如:不能连接一个QDial对象的valueChanged(int)信号到
一个QLineEdit对象的setText(QString)插槽(slot)。
在该实例中用到的是:s.connect(w, SIGNAL("signalSignature"), instance.methodName),
但当slot是一个Qt插槽而不是一个Python方法时,使用如下格式的高效:
s.connect(w, SIGNAL("signalSignature"),instance, SLOT("slotSignature"))。
可以连接多个信号到一个slot;也可以连接单个信号到多个slot;也可以连接一个信号到另一个信号。
在一些实例中,但第一信号被激发,它将引起它连接的信号被激发。

连接是通过QObject.connect()方法;断连是通过QObject.disconnect()。
实时上,很少需要自己断开连接,当一个对象被删除时,PyQt会自动断开与之相关的所有连接。

'''

import sys
from PyQt4.QtCore import *
from PyQt4.QtGui import *

class Form(QDialog):
def __init__(self,parent=None):
super(Form,self).__init__(parent)
#创建一个环形范围调节器的对象
qdial=QDial()
# 设置边缘是否可见
qdial.setNotchesVisible(True)

#创建一个整数范围调节器对象
spinbox=QSpinBox()
#创建一个水平布局框对象
hboxlayout=QHBoxLayout()
#把qdial放入hboxlayout中
hboxlayout.addWidget(qdial)
#把spinbox放入hboxlayout中
hboxlayout.addWidget(spinbox)
#hboxlayout放入到Form中
self.setLayout(hboxlayout)

#连接valueChanged()信号和spinbox的setValue()方法到qdial上
self.connect(qdial, SIGNAL("valueChanged(int)"),spinbox.setValue)
#连接valueChanged()信号和qdial的setValue()方法到spinbox上
self.connect(spinbox, SIGNAL("valueChanged(int)"),qdial.setValue)

#通过slot连接两个widget对象
#self.connect(qdial, SIGNAL("valueChanged(int)"),spinbox, SLOT("setValue(int)"))
#self.connect(spinbox, SIGNAL("valueChanged(int)"),qdial, SLOT("setValue(int)"))

#创建一个QApplication对象
app=QApplication(sys.argv)
#创建一个Form对象
form=Form()
#调用show方法显示form的窗口
form.show()
#运行app
app.exec_()
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐