PySide——Python图形化界面入门教程(四)

PySide——Python图形化界面入门教程(四)

              ——创建自己的信号槽

              ——Creating Your Own Signals and Slots

翻译自:http://pythoncentral.io/pysidepyqt-tutorial-creating-your-own-signals-and-slots/

你不必局限于Qt widget提供的信号,你可以使用Signal类来创建自己的信号。下面是一个定义的简单例子:

1 from PySide.QtCore import Signal
2 tapped = Signal()

然后,当对象需要触发信号的条件满足时,你可以使用信号的emit方法,来发出信号调用关联的槽。

thing.tapped.emit()

这样做有两个优点:第一,允许用户和你定义的对象随意交互;第二,让你的对象使用更加灵活,让自己的代码定义动作行为的影响。

一个简单的PySide信号例子

我们来定义一个简单的PunchingBag类,它只做一件事情,当punch被调用时,发出punched信号:

 1 from PySide.QtCore import QObject, Signal, Slot
 2  
 3 class PunchingBag(QObject):
 4     ''' Represents a punching bag; when you punch it, it
 5         emits a signal that indicates that it was punched. '''
 6     punched = Signal()
 7  
 8     def __init__(self):
 9         # Initialize the PunchingBag as a QObject
10         QObject.__init__(self)
11  
12     def punch(self):
13         ''' Punch the bag '''
14         self.punched.emit()

代码非常的简单:PunchingBag继承自QObject,所以它可以发出信号;它有一个称为punched的信号,不携带任何数据;并且他有一个仅仅发出punched信号的punch方法。

为了让PunchingBag更丰富一些,我们需要将它的punched信号和一个槽连接。槽简单的输出“Bag was punched”。

 1 @Slot()
 2 def say_punched():
 3     ''' Give evidence that a bag was punched. '''
 4     print('Bag was punched.')
 5  
 6 bag = PunchingBag()
 7 # Connect the bag's punched signal to the say_punched slot
 8 bag.punched.connect(say_punched)
 9 
10 # Punch the bag 10 times
11 for i in range(10):
12     bag.punch()

携带数据的PySide信号

创建信号可以完成一个非常有用的事情——携带数据。例如,你可以创建一个携带整数或者字符串的信号:

updated = Signal(int)
updated = Signal(str)

这个数据类型可以是任何Python的类型名或定义了C++类型的字符串。因为教程不假设有任何C++的知识,故我们只使用Python类型。

例子:一个发送信号的圆

我们用x,y和r定义一个圆,x、y是圆中心的坐标,r是半径。我们想要当圆被改变大小时,发送一个信号resized;当圆被移动时,也发送一个信号moved。虽然我们可以在信号的槽中检测圆的大小和位置,但是使用信号发送这些信息会更加方便。

 1 from PySide.QtCore import QObject, Signal, Slot
 2  
 3 class Circle(QObject):
 4     ''' Represents a circle defined by the x and y
 5         coordinates of its center and its radius r. '''
 6     # Signal emitted when the circle is resized,
 7     # carrying its integer radius
 8     resized = Signal(int)
 9     # Signal emitted when the circle is moved, carrying
10     # the x and y coordinates of its center.
11     moved = Signal(int, int)
12  
13     def __init__(self, x, y, r):
14         # Initialize the Circle as a QObject so it can emit signals
15         QObject.__init__(self)
16  
17         # "Hide" the values and expose them via properties
18         self._x = x
19         self._y = y
20         self._r = r
21  
22     @property
23     def x(self):
24         return self._x
25  
26     @x.setter
27     def x(self, new_x):
28         self._x = new_x
29         # After the center is moved, emit the
30         # moved signal with the new coordinates
31         self.moved.emit(new_x, self.y)
32  
33     @property
34     def y(self):
35         return self._y
36     @y.setter
37     def y(self, new_y):
38         self._y = new_y
39         # After the center is moved, emit the moved
40         # signal with the new coordinates
41         self.moved.emit(self.x, new_y)
42  
43     @property
44     def r(self):
45         return self._r
46  
47     @r.setter
48     def r(self, new_r):
49         self._r = new_r
50         # After the radius is changed, emit the
51         # resized signal with the new radius
52         self.resized.emit(new_r)

注意以下几点:

  • Circle继承自QObject所以可以发送信号
  • 同样的信号可以在不同地方发送

现在我们定义一些连接Circle的信号的槽。还记得我们上次提过的@Slot修饰符(decorator)吗?现在我们来看看如何接收携带了数据的信号。为了接收信号,我们简单的将其定义为与信号一样的结构。

1 # A slot for the "moved" signal, accepting the x and y coordinates
2 @Slot(int, int)
3 def on_moved(x, y):
4     print('Circle was moved to (%s, %s).' % (x, y))
5  
6 # A slot for the "resized" signal, accepting the radius
7 @Slot(int)
8 def on_resized(r):
9     print('Circle was resized to radius %s.' % r)

非常的简单直观。更多信息可以参考Python decorators,或者来学习这篇文章Python Decorators Overview。最后我们完成这个Circle,连接信号槽,移动并改变它的大小。

 1 c = Circle(5, 5, 4)
 2  
 3 # Connect the Circle's signals to our simple slots
 4 c.moved.connect(on_moved)
 5 c.resized.connect(on_resized)
 6  
 7 # Move the circle one unit to the right
 8 c.x += 1
 9  
10 # Increase the circle's radius by one unit
11 c.r += 1

当运行脚本的时候,你的结果应该是:

Circle was moved to (6, 5).
Circle was resized to radius 5.

现在我们对信号和槽有了更深入的了解,可以准备使用一些更高级的widgets了。下一个教程开始讨论QListWidget和QListView,两种创建表框(list box)控件的方法。

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏一个会写诗的程序员的博客

一致性(连续性)hash算法(Consistent hashing)一致性(连续性)hash算法(Consistent hashing)

Consistent hashing is a scheme that provides hash table functionality in a way t...

14920
来自专栏软件开发 -- 分享 互助 成长

分解成3NF的保持函数依赖的分解算法:

转换成3NF的保持函数依赖的分解算法: ρ={R1<U1,F1>,R2<U2,F2>,...,Rk<Uk,Fk>}是关系模式R<U,F>的一个分解,U={A1,...

38250
来自专栏丁科的专栏

pytorch 学习笔记之编写 C 扩展

在之前的文章中,我们已经了解了如何自定义 Module。这篇主要讲解pytorch利用 CFFI 进行 C 语言扩展。包括两个基本的步骤(docs):编写 C ...

1K00
来自专栏mathor

matlab—特殊变量类型与档案存取

这里举个例子,有一个学生structure,包含姓名、邮箱、学号、成绩,应该如何创建这个structure

10940
来自专栏扎心了老铁

python重试(指数退避算法)

本文实现了一个重试的装饰器,并且使用了指数退避算法。指数退避算法实现还是很简单的。先上代码再详细解释。 1、指数退避算法 欠奉。http://hugnew.co...

50040
来自专栏小白安全

【PHP】WEBSHELL各类变形方法总结

简介 WebShell的变形技术与各种防护软件的检测方法一直都在相互对抗,本篇文章就对目前常见的WebShell的变形技术进行总结。 ...

59870
来自专栏小白安全

PHP WebShell变形技术总结

简介 WebShell的变形技术与各种防护软件的检测方法一直都在相互对抗,本篇文章就对目前常见的WebShell的变形技术进行总结。 目前的防护...

89670
来自专栏CDA数据分析师

实用小工具,教你轻松转化Python通用数据格式

已独立成项目在github上面 dataformat, 涉及模块 os, getopt, sys。 1 需求 在进行hadoop测试时,需要造大量数据,例如某个...

21150
来自专栏烙馅饼喽的技术分享

用ECMAScript4 ( ActionScript3) 实现Unity的热更新 -- 使用原型链和EventTrigger

原型链是JS的必备,作为ECMAScript4,原型链也是支持的。 特别说明,ActionScript3是支持完整的面向对象继承支持的,原型链只在某些非常特殊的...

30760
来自专栏编程

说说正则表达式的使用

今日分享:正则表达式 一:正则表达式的定义及用途 正则表达式是一种特殊的字符串,字符串中的每个字符都含有特定的意义。使用者通过将正则中不同的字符组合成不同的字符...

20980

扫码关注云+社区

领取腾讯云代金券