返回顶部

PyQt5 控件学习(一个一个学习之QObject)

总的学习路线:

首先我们要知道控件之间的继承结构,并按照它去学习:

下面是基类的继承图:

 

所以,我们首先学习的是QObject 和 QWidget 这两个,然后再学其他的。

QObject 类:

1, 首先看QObject 类的继承结构

 1 from PyQt5.Qt import * #刚开始学习可以这样一下导入
 2 import sys
 3 
 4 class Window(QWidget):
 5     def __init__(self):
 6         super().__init__()
 7         self.setWindowTitle("QObject的学习")
 8         self.resize(400,400)
 9         self.set_ui()
10 
11 
12     def set_ui(self):
13         self.QObject_test()
14         
15     def QObject_test(self):
16         mros = QObject.mro()
17         for mro in mros:
18             print(mro)
19 
20 if __name__ == '__main__':
21     app =QApplication(sys.argv)
22 
23     window = Window()
24     window.show()
25 
26     sys.exit(app.exec_())
QObject 的基类

输出结果如下:

1 <class 'PyQt5.QtCore.QObject'>
2 <class 'sip.wrapper'>
3 <class 'sip.simplewrapper'>
4 <class 'object'>

2,QObject 对象名称和属性的操作

 1 from PyQt5.Qt import *  # 刚开始学习可以这样一下导入
 2 import sys
 3 
 4 
 5 class Window(QWidget):
 6     def __init__(self):
 7         super().__init__()
 8         self.setWindowTitle("QObject的学习")
 9         self.resize(400, 400)
10         self.set_ui()
11 
12     def set_ui(self):
13         self.QObject_test()
14 
15     def QObject_test(self):
16         obj = QObject()
17         obj.setObjectName("zcb")
18         print(obj.objectName())  # zcb
19 
20         obj.setProperty("notice_level", "error")
21         obj.setProperty("notice_level2", "warning")
22         print(obj.property("notice_level"))
23 
24         print(obj.dynamicPropertyNames())
25 
26 
27 if __name__ == '__main__':
28     app = QApplication(sys.argv)
29 
30     window = Window()
31     window.show()
32 
33     sys.exit(app.exec_())

输出: 

1 zcb
2 error
3 [PyQt5.QtCore.QByteArray(b'notice_level'), PyQt5.QtCore.QByteArray(b'notice_level2')]

 

下面是上述属性API 的应用场景:

>可以用用于qss的ID选择器,属性选择器,方便统一设置样式

>可以用于装饰器的信号与槽

......

关于什么是qss 样式表:

Qt样式表的概念、术语和语法与HTML的CSS样式表类似。

 

需要说的是,实际的项目中关于qss样式一般都是写在文件中,用的时候导入!

而且以后只要是QLabel的前都可以用这个样式了,

继续回到案例:

但是,如果以后想要一个新的QLabel ,但是是不想要qss样式的,这就不行了,

这涉及到了id 选择器了 ,

 

这就是objectName 的使用场景。

下面再看setProperty的使用:

首先是qss的内容:

 1 QLabel#notice {
 2     font-size :20px;
 3     color :red;
 4     border:1px solid gray;
 5     border-radius:8px;
 6 }
 7 QLabel#notice[notice_level = "normal"] {
 8     color :red;
 9     border-color:green;
10 }
11 QLabel#notice[notice_level = "warning"] {
12     color :yellow;
13     border-color:yellow;
14 }
15 QLabel#notice[notice_level = "error"] {
16     color :red;
17     border-color:red;
18 }
 1 from PyQt5.Qt import *  # 刚开始学习可以这样一下导入
 2 import sys
 3 
 4 
 5 class Window(QWidget):
 6     def __init__(self):
 7         super().__init__()
 8         self.setWindowTitle("QObject的学习")
 9         self.resize(400, 400)
10         self.set_ui()
11 
12     def set_ui(self):
13         self.QObject_test()
14 
15     def QObject_test(self):
16         with open("QObject.qss", "r") as f:
17             qApp.setStyleSheet(f.read())
18 
19         label = QLabel(self)
20         label.setText("hello 世界")
21         label.setObjectName("notice")  
22 
23         label2 = QLabel(self)
24         label2.setObjectName("notice")
25         label2.setProperty("notice_level", "warning")
26         label2.setText("你好,world")
27         label2.move(100, 100)
28 
29         label3 = QLabel(self)
30         label3.setText("你好,world")
31         label3.setObjectName("notice")
32         label3.setProperty("notice_level","error")
33         label3.move(200, 200)
34 
35 
36 if __name__ == '__main__':
37     app = QApplication(sys.argv)
38 
39     window = Window()
40     window.show()
41 
42     sys.exit(app.exec_())

输出:

以上就是关于一个控件对象,它的对象名称和属性的最大的应用场景。

 3,QObject 对象的父子关系操作

 1 from PyQt5.Qt import *  # 刚开始学习可以这样一下导入
 2 import sys
 3 
 4 
 5 class Window(QWidget):
 6     def __init__(self):
 7         super().__init__()
 8         self.setWindowTitle("QObject的学习")
 9         self.resize(400, 400)
10         self.set_ui()
11 
12     def set_ui(self):
13         self.QObject_test()
14 
15     def QObject_test(self):
16         obj0 = QObject()
17         obj1 = QObject()
18         obj2=  QObject()
19         obj3 = QObject()
20         obj4 = QObject()
21         obj5 = QObject()
22 
23         obj1.setParent(obj0)
24         obj2.setParent(obj0)
25 
26         obj3.setParent(obj1)
27 
28         obj4.setParent(obj2)
29         obj5.setParent(obj2)
30 
31 if __name__ == '__main__':
32     app = QApplication(sys.argv)
33 
34     window = Window()
35     window.show()
36 
37     sys.exit(app.exec_())
构造父子图

注:一个对象只能设置一个父对象,而且是按后设置的算!

获取子对象-----children():

 1 from PyQt5.Qt import *  # 刚开始学习可以这样一下导入
 2 import sys
 3 
 4 
 5 class Window(QWidget):
 6     def __init__(self):
 7         super().__init__()
 8         self.setWindowTitle("QObject的学习")
 9         self.resize(400, 400)
10         self.set_ui()
11 
12     def set_ui(self):
13         self.QObject_test()
14 
15     def QObject_test(self):
16         obj0 = QObject()
17         obj1 = QObject()
18         obj2=  QObject()
19         obj3 = QObject()
20         obj4 = QObject()
21         obj5 = QObject()
22 
23         obj1.setParent(obj0)
24         obj2.setParent(obj0)
25 
26         obj3.setParent(obj1)
27 
28         obj4.setParent(obj2)
29         obj5.setParent(obj2)
30 
31         print(obj0.children())  #注:这个子对象是直接的子对象。
32 
33 if __name__ == '__main__':
34     app = QApplication(sys.argv)
35 
36     window = Window()
37     window.show()
38 
39     sys.exit(app.exec_())
获取直接子对象

输出:

 1 [<PyQt5.QtCore.QObject object at 0x00000242FCCA9CA8>,

 2  <PyQt5.QtCore.QObject object at 0x00000242FCCA9D38>] 

获取一个子对象-----findchild():

 

那么,如果想要得到另一个子对象,obj2 怎么搞呢?

可以使用objectName 来做区分:

 1 from PyQt5.Qt import *  # 刚开始学习可以这样一下导入
 2 import sys
 3 
 4 
 5 class Window(QWidget):
 6     def __init__(self):
 7         super().__init__()
 8         self.setWindowTitle("QObject的学习")
 9         self.resize(400, 400)
10         self.set_ui()
11 
12     def set_ui(self):
13         self.QObject_test()
14 
15     def QObject_test(self):
16         obj0 = QObject()
17         obj1 = QObject()
18         obj2=  QObject()
19         obj3 = QObject()
20         obj4 = QObject()
21         obj5 = QObject()
22         str_pr ="obj"
23         for i in range(6):  # 打印各个对象变量
24             name = str_pr+str(i)
25             print(eval(name))
26 
27 
28 
29         obj1.setParent(obj0)
30         obj2.setParent(obj0)
31         obj2.setObjectName("2")
32         obj3.setParent(obj1)
33 
34         obj4.setParent(obj2)
35         obj5.setParent(obj2)
36 
37         print(obj0.findChild(QObject,"2"))   #第二个参数为对象的名称
38 
39 if __name__ == '__main__':
40     app = QApplication(sys.argv)
41 
42     window = Window()
43     window.show()
44 
45     sys.exit(app.exec_())
findChild的第二个参数查找

这样就找到了obj2 !

 

现在如果从obj0直接查找obj3 能找到吗?

 1 from PyQt5.Qt import *  # 刚开始学习可以这样一下导入
 2 import sys
 3 
 4 
 5 class Window(QWidget):
 6     def __init__(self):
 7         super().__init__()
 8         self.setWindowTitle("QObject的学习")
 9         self.resize(400, 400)
10         self.set_ui()
11 
12     def set_ui(self):
13         self.QObject_test()
14 
15     def QObject_test(self):
16         obj0 = QObject()
17         obj1 = QObject()
18         obj2=  QObject()
19         obj3 = QObject()
20         obj4 = QObject()
21         obj5 = QObject()
22         str_pr ="obj"
23         for i in range(6):  # 打印各个对象变量
24             name = str_pr+str(i)
25             print("obj{}".format(i),eval(name))
26 
27 
28 
29         obj1.setParent(obj0)
30         obj2.setParent(obj0)
31         obj2.setObjectName("2")
32         obj3.setParent(obj1)
33         obj3.setObjectName("3")
34 
35         obj4.setParent(obj2)
36         obj5.setParent(obj2)
37 
38         print(obj0.findChild(QObject,"3"))   #第二个参数为对象的名称
39 
40 if __name__ == '__main__':
41     app = QApplication(sys.argv)
42 
43     window = Window()
44     window.show()
45 
46     sys.exit(app.exec_())
47     '''
48     obj0 <PyQt5.QtCore.QObject object at 0x000002B5FA8E9C18>
49     obj1 <PyQt5.QtCore.QObject object at 0x000002B5FA8E9CA8>
50     obj2 <PyQt5.QtCore.QObject object at 0x000002B5FA8E9D38>
51     obj3 <PyQt5.QtCore.QObject object at 0x000002B5FA8E9DC8>
52     obj4 <PyQt5.QtCore.QObject object at 0x000002B5FA8E9E58>
53     obj5 <PyQt5.QtCore.QObject object at 0x000002B5FA8E9EE8>
54     <PyQt5.QtCore.QObject object at 0x000002B5FA8E9DC8>       
55         
56     '''
从obj0 直接查找Obj3

也找到了,这里涉及到findChild的第三个参数了就,

它默认是按递归查找的,也可以设置为只查找子对象中的。

这就是findChild的用法。

----------- findChildren() 查询全部的子对象!

 

 父子关系操作的应用场景(1)

当父对象销毁的时候,子对象也会被销毁。

因此,我们看到了输出的 obj2对象被释放了!

 

 

这时就看不到了!

 1 from PyQt5.Qt import *  # 刚开始学习可以这样一下导入
 2 import sys
 3 
 4 
 5 class Window(QWidget):
 6     def __init__(self):
 7         super().__init__()
 8         self.setWindowTitle("QObject的学习")
 9         self.resize(400, 400)
10         self.set_ui()
11 
12     def set_ui(self):
13         self.QObject_test()
14 
15     def QObject_test(self):
16         obj1= QObject()
17         self.obj = obj1
18         obj2 = QObject()
19 
20         #监听obj2
21         obj2.destroyed.connect(lambda :print("obj2被释放"))
22         del self.obj
23 
24 
25 
26 if __name__ == '__main__':
27     app = QApplication(sys.argv)
28 
29     window = Window()
30     window.show()
31 
32     sys.exit(app.exec_())
33     '''
34     obj2被释放
35 
36     '''
一旦父对象被释放,子对象也自动被释放

所以,父子控件释放时,如果父控件被释放了,子控件也会被释放!

这就是QT对象内存管理机制!

  父子关系操作的应用场景(2)

 

 代码:

 

 1     app = QApplication(sys.argv)
 2 
 3     win1 = QWidget()
 4     win1.setStyleSheet("background-color:red;")
 5     win1.show()
 6 
 7     win2 = QWidget()
 8     win2.setStyleSheet("background-color:green;")
 9     win2.show()
10 
11     sys.exit(app.exec_())

输出:

 

 将绿的窗口放到红的窗口中:

 1 app = QApplication(sys.argv)
 2 
 3 win1 = QWidget()
 4 win1.setStyleSheet("background-color:red;")
 5 win1.show()
 6 
 7 win2 = QWidget()
 8 win2.setStyleSheet("background-color:green;")
 9 win2.resize(100,100)
10 win2.setParent(win1)  #将win2 放到win1 窗口中
11 win2.show()
12 
13 sys.exit(app.exec_())

这就是QObject 中的父子关系延伸到QWidget()对象的父子对象之间!

 

 1 win_root = QWidget()
 2 
 3 label1 = QLabel()
 4 label1.setText("Label1")
 5 label1.setParent(win_root)
 6 
 7 win_root.show()
 8 sys.exit(app.exec_())
 9 #=============注意二者的区别================
10 win_root = QWidget()
11 
12 label1 = QLabel(win_root)
13 label1.setText("Label1")
14 
15 win_root.show()
16 sys.exit(app.exec_())

 

如下代码:(要求将Label标签背景修改颜色为cyan )

当然可以用qss ,但是也可以遍历子控件:

 1     win_root = QWidget()
 2 
 3     label1 = QLabel()
 4     label1.setText("Label1")
 5     label1.setParent(win_root)
 6 
 7     label2 = QLabel()
 8     label2.setText("Label2")
 9     label2.setParent(win_root)
10     label2.move(50,50)
11 
12 
13     btn = QPushButton(win_root)
14     btn.setText("btn")
15     btn.move(100,100)
16 
17 
18     for sub_widget in win_root.findChildren(QLabel):
19         print(sub_widget)
20         sub_widget.setStyleSheet("background-color:cyan;")
21 
22     win_root.show()
遍历子控件

结果如下:

 

以上想要说的知识点有:

QObject对象的父子关系,以及Qt 内存管理机制

QWidget内的父子控件关系

4,QObject 对象的信号的操作

 

首先我们要先看信号与槽机制。它是QT中核心的概念。

所有继承自QWidget的控件都支持“信号-槽”机制。(QObject 也支持信号与槽机制)

 

 

 

多个信号还可以连接同一个槽函数!

 下面用代码说明信号的操作:

QObject()的对象提供了两个信号! 

1 obj = QObject()
2 # obj.destroyed  #当对象被销毁时会触发这个信号
3 # obj.objectNameChanged # 当对象的名称改变时触发这个信号
QObject 对象的两个信号
 1 from PyQt5.Qt import *  # 刚开始学习可以这样一下导入
 2 import sys
 3 
 4 
 5 class Window(QWidget):
 6     def __init__(self):
 7         super().__init__()
 8         self.setWindowTitle("QObject的学习")
 9         self.resize(400, 400)
10         self.set_ui()
11 
12     def set_ui(self):
13         self.QObject_signal_test()
14 
15     def QObject_signal_test(self):
16         self.obj = QObject()
17         def destrroy_slot():
18             print("对象被释放了")
19         self.obj.destroyed.connect(destrroy_slot)
20 
21         del self.obj  
22         
23 if __name__ == '__main__':
24     app = QApplication(sys.argv)
25 
26     window = Window()
27     window.show()
28 
29     sys.exit(app.exec_())
30     '''
31     对象被释放了
32 
33     '''
obj.destroy信号的使用
 1 from PyQt5.Qt import *  # 刚开始学习可以这样一下导入
 2 import sys
 3 
 4 
 5 class Window(QWidget):
 6     def __init__(self):
 7         super().__init__()
 8         self.setWindowTitle("QObject的学习")
 9         self.resize(400, 400)
10         self.set_ui()
11 
12     def set_ui(self):
13         self.QObject_signal_test()
14 
15     def QObject_signal_test(self):
16         self.obj = QObject()
17         def nameChanged_slot():
18             print("对象名称被修改了")
19         self.obj.objectNameChanged.connect(nameChanged_slot)
20 
21         self.obj.setObjectName("zcb")
22         self.obj.setObjectName("tom")
23 
24 
25 if __name__ == '__main__':
26     app = QApplication(sys.argv)
27 
28     window = Window()
29     window.show()
30 
31     sys.exit(app.exec_())
32     '''
33     对象名称被修改了
34     对象名称被修改了
35 
36     '''
obj.objectNameChanged信号使用

还有一定要补充:有些信号在发射的时候,会伴随着给外界传递参数,

如果我们想看的话,我们用槽函数接收它就行。如下:

 

 1 from PyQt5.Qt import *  # 刚开始学习可以这样一下导入
 2 import sys
 3 
 4 
 5 class Window(QWidget):
 6     def __init__(self):
 7         super().__init__()
 8         self.setWindowTitle("QObject的学习")
 9         self.resize(400, 400)
10         self.set_ui()
11 
12     def set_ui(self):
13         self.QObject_signal_test()
14 
15     def QObject_signal_test(self):
16         self.obj = QObject()
17         self.obj.setObjectName("对象0")
18         def destroyed_slot(arg):  # 会自动接收信号发送的参数
19             print("{}的对象被干死了".format(arg.objectName()))
20         self.obj.destroyed.connect(destroyed_slot)
21 
22         del self.obj
23 
24 
25 if __name__ == '__main__':
26     app = QApplication(sys.argv)
27 
28     window = Window()
29     window.show()
30 
31     sys.exit(app.exec_())
32     '''
33     对象0的对象干死了
34     '''
接收obj.destroyed信号发出的参数
 1 from PyQt5.Qt import *  # 刚开始学习可以这样一下导入
 2 import sys
 3 
 4 
 5 class Window(QWidget):
 6     def __init__(self):
 7         super().__init__()
 8         self.setWindowTitle("QObject的学习")
 9         self.resize(400, 400)
10         self.set_ui()
11 
12     def set_ui(self):
13         self.QObject_signal_test()
14 
15     def QObject_signal_test(self):
16         self.obj = QObject()
17         self.obj.setObjectName("对象0")
18         def objectNameChanged_slot(arg):  # 会自动接收信号发送的参数
19             print("对象的名字被修改成了{}".format(arg))
20         self.obj.objectNameChanged.connect(objectNameChanged_slot)
21 
22         self.obj.setObjectName("tom")
23 
24 
25 if __name__ == '__main__':
26     app = QApplication(sys.argv)
27 
28     window = Window()
29     window.show()
30 
31     sys.exit(app.exec_())
32     '''
33     对象的名字被修改成了tom
34     '''
接收obj.objectNameChanged信号传出得到参数

 

 1 from PyQt5.Qt import *  # 刚开始学习可以这样一下导入
 2 import sys
 3 
 4 
 5 class Window(QWidget):
 6     def __init__(self):
 7         super().__init__()
 8         self.setWindowTitle("QObject的学习")
 9         self.resize(400, 400)
10         self.set_ui()
11 
12     def set_ui(self):
13         self.QObject_signal_test()
14 
15     def QObject_signal_test(self):
16         self.obj = QObject()
17         self.obj.setObjectName("对象0")
18         def objectNameChanged_slot(arg):  # 会自动接收信号发送的参数
19             print("对象的名字被修改成了{}".format(arg))
20         self.obj.objectNameChanged.connect(objectNameChanged_slot)
21 
22         self.obj.setObjectName("tom")
23         self.obj.objectNameChanged.disconnect()  # 取消信号和槽之间的联系
24 
25         self.obj.setObjectName("jack")
26 
27 if __name__ == '__main__':
28     app = QApplication(sys.argv)
29 
30     window = Window()
31     window.show()
32 
33     sys.exit(app.exec_())
34     '''
35     对象的名字被修改成了tom  # 后面的jack 没有被打印
36     '''
使用disconnect()来取消信号的连接

 1 from PyQt5.Qt import *  # 刚开始学习可以这样一下导入
 2 import sys
 3 
 4 #=======================需求:要求只是中间的槽函数不被触发===================
 5 # class Window(QWidget):
 6 #     def __init__(self):
 7 #         super().__init__()
 8 #         self.setWindowTitle("QObject的学习")
 9 #         self.resize(400, 400)
10 #         self.set_ui()
11 #
12 #     def set_ui(self):
13 #         self.QObject_signal_test()
14 #
15 #     def QObject_signal_test(self):
16 #         self.obj = QObject()
17 #         self.obj.setObjectName("对象0")
18 #         def objectNameChanged_slot(arg):  # 会自动接收信号发送的参数
19 #             print("对象的名字被修改成了{}".format(arg))
20 #         self.obj.objectNameChanged.connect(objectNameChanged_slot)
21 #
22 #         self.obj.setObjectName("tom")  #触发
23 #         self.obj.objectNameChanged.disconnect()
24 #
25 #         self.obj.setObjectName("jack")  #不触发
26 #
27 #         self.obj.objectNameChanged.connect(objectNameChanged_slot)
28 #         self.obj.setObjectName("richel")   #也想触发
29 #
30 # if __name__ == '__main__':
31 #     app = QApplication(sys.argv)
32 #
33 #     window = Window()
34 #     window.show()
35 #
36 #     sys.exit(app.exec_())
37 # '''
38 # 对象的名字被修改成了tom
39 # 对象的名字被修改成了richel
40 # '''
41 #=======================上面的太麻烦了=================================
42 class Window(QWidget):
43     def __init__(self):
44         super().__init__()
45         self.setWindowTitle("QObject的学习")
46         self.resize(400, 400)
47         self.set_ui()
48 
49     def set_ui(self):
50         self.QObject_signal_test()
51 
52     def QObject_signal_test(self):
53         self.obj = QObject()
54         self.obj.setObjectName("对象0")
55         def objectNameChanged_slot(arg):  # 会自动接收信号发送的参数
56             print("对象的名字被修改成了{}".format(arg))
57         self.obj.objectNameChanged.connect(objectNameChanged_slot)
58 
59         self.obj.setObjectName("tom")  #触发
60 
61         self.obj.blockSignals(True)  # 临时阻断self.obj所有信号的连接(注不是断开连接)
62 
63         self.obj.setObjectName("jack")  #不触发
64         self.obj.blockSignals(False)  # 将临时阻断去掉
65 
66         self.obj.setObjectName("richel")   #也想触发
67 
68 if __name__ == '__main__':
69     app = QApplication(sys.argv)
70 
71     window = Window()
72     window.show()
73 
74     sys.exit(app.exec_())
使用blockSignals()进行临时阻断的设置

 1 from PyQt5.Qt import *  # 刚开始学习可以这样一下导入
 2 import sys
 3 
 4 class Window(QWidget):
 5     def __init__(self):
 6         super().__init__()
 7         self.setWindowTitle("QObject的学习")
 8         self.resize(400, 400)
 9         self.set_ui()
10 
11     def set_ui(self):
12         self.QObject_signal_test()
13 
14     def QObject_signal_test(self):
15         self.obj = QObject()
16         self.obj.setObjectName("对象0")
17         def objectNameChanged_slot(arg):  # 会自动接收信号发送的参数
18             print("对象的名字被修改成了{}".format(arg))
19         self.obj.objectNameChanged.connect(objectNameChanged_slot)
20 
21         self.obj.setObjectName("tom")
22         print(self.obj.signalsBlocked())  # False 表示没有被临时阻断
23         self.obj.blockSignals(True)
24         print(self.obj.signalsBlocked())  # True  表示被临时阻断
25 
26 
27         self.obj.setObjectName("jack")
28         self.obj.blockSignals(False)
29 
30         self.obj.setObjectName("richel")
31 
32 if __name__ == '__main__':
33     app = QApplication(sys.argv)
34 
35     window = Window()
36     window.show()
37 
38     sys.exit(app.exec_())
使用signalsBlocked() 获取是否被了临时阻断

 1 from PyQt5.Qt import *  # 刚开始学习可以这样一下导入
 2 import sys
 3 
 4 class Window(QWidget):
 5     def __init__(self):
 6         super().__init__()
 7         self.setWindowTitle("QObject的学习")
 8         self.resize(400, 400)
 9         self.set_ui()
10 
11     def set_ui(self):
12         self.QObject_signal_test()
13 
14     def QObject_signal_test(self):
15         self.obj = QObject()
16         self.obj.setObjectName("对象0")
17         def objectNameChanged_slot1(arg):
18             print("对象的名字被修改成了{}".format(arg))
19 
20         def objectNameChanged_slot2(arg):
21             print("对象的名字被修改成了{}".format(arg))
22 
23         self.obj.objectNameChanged.connect(objectNameChanged_slot1)
24         self.obj.objectNameChanged.connect(objectNameChanged_slot2)
25 
26         print("信号有{}个槽函数".format(self.obj.receivers(self.obj.objectNameChanged)))
27 
28 
29 if __name__ == '__main__':
30     app = QApplication(sys.argv)
31 
32     window = Window()
33     window.show()
34 
35     sys.exit(app.exec_())
36     
37     '''
38     信号有2个槽函数
39     '''
利用receivers() 查看指定信号所对应的槽函数的个数

这时基本使用,高级使用后面说!

信号与槽的案例:

 1 from PyQt5.Qt import *  # 刚开始学习可以这样一下导入
 2 import sys
 3 
 4 class Window(QWidget):
 5     def __init__(self):
 6         super().__init__()
 7         self.setWindowTitle("QObject的学习")
 8         self.resize(400, 400)
 9         self.set_ui()
10 
11     def set_ui(self):
12         self.QObject_signal_test()
13 
14     def QObject_signal_test(self):
15         btn = QPushButton(self)
16         btn.setText("点击我呀")
17 
18         def clicked_slot():
19             print("点我干啥?")
20 
21         btn.clicked.connect(clicked_slot)
22 
23 
24 if __name__ == '__main__':
25     app = QApplication(sys.argv)
26 
27     window = Window()
28     window.show()
29 
30     sys.exit(app.exec_())
31 
32     '''
33     点我干啥?
34     点我干啥?
35     点我干啥?
36     点我干啥?
37     点我干啥?
38     点我干啥?
39     点我干啥?
40     '''
案例一:点击按钮显示内容
 1 from PyQt5.Qt import *  # 刚开始学习可以这样一下导入
 2 import sys
 3 
 4 if __name__ == '__main__':
 5     app = QApplication(sys.argv)
 6 
 7     window = QWidget()
 8     #如何自动的添加前缀 ZCB
 9     # window.setWindowTitle("ZCB_helloworld")
10     # window.setWindowTitle("ZCB_你好世界")
11     # window.setWindowTitle("ZCB_你好中国")
12 
13     def windowTitleChanged_slot(arg):
14         print("dasfjkldsafj",arg)
15         window.setWindowTitle("ZCB"+arg)  #这样调会陷入死循环
16 
17     window.windowTitleChanged.connect(windowTitleChanged_slot)
18 
19     window.setWindowTitle("helloworld")
20 
21     window.show()
22 
23     sys.exit(app.exec_())
24 
25     '''
26     dasfjkldsafj helloworld
27     dasfjkldsafj ZCBhelloworld
28     dasfjkldsafj ZCBZCBhelloworld
29     dasfjkldsafj ZCBZCBZCBhelloworld
30     dasfjkldsafj ZCBZCBZCBZCBhelloworld
31     dasfjkldsafj ZCBZCBZCBZCBZCBhelloworld
32     dasfjkldsafj ZCBZCBZCBZCBZCBZCBhelloworld
33     dasfjkldsafj ZCBZCBZCBZCBZCBZCBZCBhelloworld
34     dasfjkldsafj ZCBZCBZCBZCBZCBZCBZCBZCBhelloworld
35     dasfjkldsafj ZCBZCBZCBZCBZCBZCBZCBZCBZCBhelloworld
36     dasfjkldsafj ZCBZCBZCBZCBZCBZCBZCBZCBZCBZCBhelloworld
37     dasfjkldsafj ZCBZCBZCBZCBZCBZCBZCBZCBZCBZCBZCBhelloworld
38     '''
案例二:自动添加前缀ZCB(版本一)(陷入死循环)
 1 from PyQt5.Qt import *  # 刚开始学习可以这样一下导入
 2 import sys
 3 
 4 if __name__ == '__main__':
 5     app = QApplication(sys.argv)
 6 
 7     window = QWidget()
 8     #如何自动的添加前缀 ZCB
 9     # window.setWindowTitle("ZCB_helloworld")
10     # window.setWindowTitle("ZCB_你好世界")
11     # window.setWindowTitle("ZCB_你好中国")
12 
13     def windowTitleChanged_slot(arg):
14         window.blockSignals(True)  #临时阻塞信号
15         window.setWindowTitle("ZCB"+arg)
16         window.blockSignals(False) #再次开启信号的连接
17         
18     window.windowTitleChanged.connect(windowTitleChanged_slot)
19 
20     window.setWindowTitle("helloworld")
21 
22     window.show()
23 
24     sys.exit(app.exec_())
案例二:自动添加标题前缀ZCB(版本二)(解决死循环问题)

 

 5,QObject 对象之类型判定

QObject 的第四个功能是类型判定

 1 from PyQt5.Qt import *  # 刚开始学习可以这样一下导入
 2 import sys
 3 
 4 
 5 class Window(QWidget):
 6     def __init__(self):
 7         super().__init__()
 8         self.setWindowTitle("QObject的学习")
 9         self.resize(400, 400)
10         self.set_ui()
11 
12     def set_ui(self):
13         self.QObject_type_judge()
14 
15     def QObject_type_judge(self):
16         obj = QObject()
17         w = QWidget()
18         btn = QPushButton()
19         label = QLabel()
20 
21         obj_list = [obj, w, btn, label]
22         for o in obj_list:
23             print(o.isWidgetType())
24 
25 
26 if __name__ == '__main__':
27     app = QApplication(sys.argv)
28 
29     window = Window()
30     window.show()
31 
32     sys.exit(app.exec_())
33 '''
34     输出:
35         False
36         True
37         True
38         True
39 '''
利用isWidgetType()判定是否为控件

这个继承,直接或间接都行!

 1 from PyQt5.Qt import *  # 刚开始学习可以这样一下导入
 2 import sys
 3 
 4 
 5 class Window(QWidget):
 6     def __init__(self):
 7         super().__init__()
 8         self.setWindowTitle("QObject的学习")
 9         self.resize(400, 400)
10         self.set_ui()
11 
12     def set_ui(self):
13         self.QObject_type_judge()
14 
15     def QObject_type_judge(self):
16         obj = QObject()
17         w = QWidget()
18         btn = QPushButton()
19         label = QLabel()
20 
21         obj_list = [obj, w, btn, label]
22 
23         for o in obj_list:
24             print(o.inherits("QWidget"))
25 
26 
27 
28 if __name__ == '__main__':
29     app = QApplication(sys.argv)
30 
31     window = Window()
32     window.show()
33 
34     sys.exit(app.exec_())
35 '''
36     输出:
37         False
38         True
39         True
40         True
41 '''
利用isherits() 来判定对象是否继承自某个控件

它的应用场景:

我们这里可以用findChildren()来做。

但是,也可以对其进行过滤:

 1 from PyQt5.Qt import *  # 刚开始学习可以这样一下导入
 2 import sys
 3 
 4 
 5 class Window(QWidget):
 6     def __init__(self):
 7         super().__init__()
 8         self.setWindowTitle("QObject的学习")
 9         self.resize(400, 400)
10         self.set_ui()
11 
12     def set_ui(self):
13         self.QObject_type_judge()
14 
15     def QObject_type_judge(self):
16         label_1 = QLabel(self)
17         label_1.setText("Life is short")
18 
19         label_2 = QLabel(self)
20         label_2.setText("I learn Python")
21         label_2.move(100,100)
22 
23         btn = QPushButton(self)
24         btn.setText("点我")
25         btn.move(200,200)
26 
27         for widget in self.children():
28             if widget.inherits("QLabel"):
29                 widget.setStyleSheet("background-color:cyan;")
30 
31 if __name__ == '__main__':
32     app = QApplication(sys.argv)
33 
34     window = Window()
35     window.show()
36 
37     sys.exit(app.exec_())
使用isherits("QLabel") 进行过滤

类型判定主要做的就是控件过滤!

6,QObject 对象之对象删除

 1 from PyQt5.Qt import *  # 刚开始学习可以这样一下导入
 2 import sys
 3 
 4 
 5 class Window(QWidget):
 6     def __init__(self):
 7         super().__init__()
 8         self.setWindowTitle("QObject的学习")
 9         self.resize(400, 400)
10         self.set_ui()
11 
12     def set_ui(self):
13         self.QObject_delete()
14 
15     def QObject_delete(self):
16 
17         obj_1 = QObject()
18         self.obj = obj_1
19         obj_2 = QObject()
20         obj_3 = QObject()
21 
22         obj_3.setParent(obj_2)
23         obj_2.setParent(obj_1)
24 
25         obj_1.destroyed.connect(lambda :print("obj1 被释放"))
26         obj_2.destroyed.connect(lambda :print("obj2 被释放"))
27         obj_3.destroyed.connect(lambda :print("obj3 被释放"))
28 
29         # del obj_2 # 这时候没有任何效果,因为obj_2 还被obj_1 引用着呢!
30         obj_2.deleteLater()  # 删除对象时,也会解除它与父对象的关系,而且是稍后删除。
31         print(obj_1.children())
32 
33 
34 if __name__ == '__main__':
35     app = QApplication(sys.argv)
36 
37     window = Window()
38     window.show()
39 
40     sys.exit(app.exec_())
41 '''
42     输出:
43         [<PyQt5.QtCore.QObject object at 0x000001A0A34C6E58>]  #这是因为稍后删除
44         obj2 被释放
45         obj3 被释放
46 '''
deleteLater()稍后删除 

 总结:删除控件时不能使用del 删除控件,删除不了!

要用deleteLater() 删除,而且这个删除是稍后删除!

7,QObject 对象之事件处理

这里涉及到Qt中的事件机制。

 

 

 

下面是代码演示简略版本的Qt事件处理机制:

我们通过继承QApplication类,并修改nodify() 方法实现对事件的拦截。这叫做重写父类的方法!

重写是override!

 

 1 from PyQt5.Qt import *  # 刚开始学习可以这样一下导入
 2 import sys
 3 
 4 class App(QApplication):
 5     # def notify(self, QObject, QEvent):  #参数:一个是事件的接收者,一个是 被包装的事件对象
 6     #     pass
 7     def notify(self, receiver, event):
 8         print(receiver,event)  #此时肯定会挂,因为我们重写了父类方法,但是却没有作为
 9 
10 app = App(sys.argv)
11 
12 window = QWidget()
13 
14 btn=  QPushButton(window)
15 btn.setText("按钮")
16 btn.move(100,100)
17 
18 btn.pressed.connect(lambda :print("I am here"))
19     #鼠标只要是按下就行,而btn.clicked  鼠标是点击之后又起来
20 
21 
22 
23 window.show()
24 
25 
26 sys.exit(app.exec_())
重写父类方法,但是却不知如何办

其实,我们可以在重写的方法中调用父类的方法:

 1 from PyQt5.Qt import *  # 刚开始学习可以这样一下导入
 2 import sys
 3 
 4 class App(QApplication):
 5     # def notify(self, QObject, QEvent):  #参数:一个是事件的接收者,一个是 被包装的事件对象
 6     #     pass
 7     def notify(self, receiver, event):
 8         print(receiver,event)
 9         super().notify(receiver,event)
10 
11 
12 
13 app = App(sys.argv)
14 
15 window = QWidget()
16 
17 btn=  QPushButton(window)
18 btn.setText("按钮")
19 btn.move(100,100)
20 
21 btn.pressed.connect(lambda :print("I am here"))
22     #鼠标只要是按下就行,而btn.clicked  鼠标是点击之后又起来
23 
24 
25 
26 window.show()
27 
28 
29 sys.exit(app.exec_())
此时还是不太行

因为还缺少返回值:

 1 from PyQt5.Qt import *  # 刚开始学习可以这样一下导入
 2 import sys
 3 
 4 class App(QApplication):
 5     # def notify(self, QObject, QEvent):  #参数:一个是事件的接收者,一个是 被包装的事件对象
 6     #     pass
 7     def notify(self, receiver, event):
 8         print(receiver,event)
 9         return super().notify(receiver,event)
10 
11 
12 
13 app = App(sys.argv)
14 
15 window = QWidget()
16 
17 btn=  QPushButton(window)
18 btn.setText("按钮")
19 btn.move(100,100)
20 
21 btn.pressed.connect(lambda :print("I am here"))
22     #鼠标只要是按下就行,而btn.clicked  鼠标是点击之后又起来
23 
24 
25 
26 window.show()
27 
28 
29 sys.exit(app.exec_())
带有返回值的

以上就是如何重写父类的方法还保证不出错!

此时会打印一堆,但是我们只想要的是点击鼠标按下的事件的反应:
于是就要用到过滤了。

 1 from PyQt5.Qt import *  # 刚开始学习可以这样一下导入
 2 import sys
 3 
 4 
 5 class App(QApplication):
 6     # def notify(self, QObject, QEvent):  #参数:一个是事件的接收者,一个是 被包装的事件对象
 7     #     pass
 8     def notify(self, receiver, event):
 9         if receiver.inherits("QPushButton"):
10             print(receiver, event)
11         return super().notify(receiver, event)
12 
13 
14 app = App(sys.argv)
15 
16 window = QWidget()
17 
18 btn = QPushButton(window)
19 btn.setText("按钮")
20 btn.move(100, 100)
21 
22 btn.pressed.connect(lambda: print("I am here"))
23 # 鼠标只要是按下就行,而btn.clicked  鼠标是点击之后又起来
24 
25 
26 
27 window.show()
28 
29 sys.exit(app.exec_())
此时依然打印了很多

我们其实还可以对PushButton的接收到的事件进行过滤:

 1 from PyQt5.Qt import *  # 刚开始学习可以这样一下导入
 2 import sys
 3 
 4 
 5 class App(QApplication):
 6     # def notify(self, QObject, QEvent):  #参数:一个是事件的接收者,一个是 被包装的事件对象
 7     #     pass
 8     QEvent
 9     def notify(self, receiver, event):  # event的类是  QEvent 里有方法type() 判断类型
10 
11         if receiver.inherits("QPushButton") and event.type() ==  QEvent.MouseButtonPress:
12             print(receiver, event)
13         return super().notify(receiver, event)
14 
15 
16 app = App(sys.argv)
17 
18 window = QWidget()
19 
20 btn = QPushButton(window)
21 btn.setText("按钮")
22 btn.move(100, 100)
23 
24 btn.pressed.connect(lambda: print("I am here"))
25 # 鼠标只要是按下就行,而btn.clicked  鼠标是点击之后又起来
26 
27 
28 
29 window.show()
30 
31 sys.exit(app.exec_())
32 
33 '''
34     输出:
35     <PyQt5.QtWidgets.QPushButton object at 0x0000020E2169BB88> <PyQt5.QtGui.QMouseEvent object at 0x0000020E2169BD38>
36     I am here
37 '''
最终版本
 1 from PyQt5.Qt import *  # 刚开始学习可以这样一下导入
 2 import sys
 3 
 4 
 5 class App(QApplication):
 6     # def notify(self, QObject, QEvent):  #参数:一个是事件的接收者,一个是 被包装的事件对象
 7     #     pass
 8     QEvent
 9     def notify(self, receiver, event):
10 
11         if receiver.inherits("QPushButton") and event.type() ==  QEvent.MouseButtonPress:
12             print(receiver, event)  #此时 pressed 信号就不会被发出去了
13         else:
14             return super().notify(receiver, event)
15 
16 
17 app = App(sys.argv)
18 
19 window = QWidget()
20 
21 btn = QPushButton(window)
22 btn.setText("按钮")
23 btn.move(100, 100)
24 
25 btn.pressed.connect(lambda: print("I am here"))
26 # 鼠标只要是按下就行,而btn.clicked  鼠标是点击之后又起来
27 
28 
29 
30 window.show()
31 
32 sys.exit(app.exec_())
33 
34 '''
35     输出:
36     <PyQt5.QtWidgets.QPushButton object at 0x000002704FE5BB88> <PyQt5.QtGui.QMouseEvent object at 0x000002704FE5BD38>
37 
38     Process finished with exit code -1073740791 (0xC0000409)
39 '''
模拟使得pressed信号发不出去,而且程序点击之后也崩了

再次拦截:(在调用receiver对象的方法的时候拦截,这里通过重写QPushButton的方法。)

 1 from PyQt5.Qt import *  # 刚开始学习可以这样一下导入
 2 import sys
 3 
 4 
 5 class App(QApplication):
 6     # def notify(self, QObject, QEvent):  #参数:一个是事件的接收者,一个是 被包装的事件对象
 7     #     pass
 8     QEvent
 9     def notify(self, receiver, event):
10 
11         if receiver.inherits("QPushButton") and event.type() ==  QEvent.MouseButtonPress:
12             print(receiver, event)  #此时 pressed 信号就不会被发出去了
13 
14         return super().notify(receiver, event)
15 
16 
17 class Btn(QPushButton):
18 
19     # def event(self, QEvent):
20 
21     def event(self, event):  # 继续往下分发
22         if event.type() == QEvent.MouseButtonPress:
23             print(event)
24         return super().event(event)   # 继续往下分发
25 app = App(sys.argv)
26 window = QWidget()
27 
28 btn = Btn(window)
29 btn.setText("按钮")
30 btn.move(100, 100)
31 
32 btn.pressed.connect(lambda: print("I am here"))
33 # 鼠标只要是按下就行,而btn.clicked  鼠标是点击之后又起来
34 
35 
36 window.show()
37 
38 sys.exit(app.exec_())
39 
40 '''
41     输出:
42     <__main__.Btn object at 0x000001EE54012CA8> <PyQt5.QtGui.QMouseEvent object at 0x000001EE54012E58>
43     <PyQt5.QtGui.QMouseEvent object at 0x000001EE54012E58>
44     I am here
45 '''
重写QPushButton 中的event()方法

此后,QPushButton 中的方法会再次调用相应的方法去发射对应的信号。

例如:当鼠标只要按下就会调用mousePressEvent() 方法,最终发射出pressed的信号。

我们也将这个函数给重写了:

 1 from PyQt5.Qt import *  # 刚开始学习可以这样一下导入
 2 import sys
 3 
 4 
 5 class App(QApplication):
 6     # def notify(self, QObject, QEvent):  #参数:一个是事件的接收者,一个是 被包装的事件对象
 7     #     pass
 8     QEvent
 9     def notify(self, receiver, event):
10 
11         if receiver.inherits("QPushButton") and event.type() ==  QEvent.MouseButtonPress:
12             print(receiver, event)  #此时 pressed 信号就不会被发出去了
13 
14         return super().notify(receiver, event)
15 
16 
17 class Btn(QPushButton):
18 
19     # def event(self, QEvent):
20 
21     def event(self, event):  # 继续往下分发
22         if event.type() == QEvent.MouseButtonPress:
23             print(event)
24         return super().event(event)   # 继续往下分发
25     def mousePressEvent(self, *args, **kwargs):
26         print("请注意我,我不是I am here")
27 
28 
29 app = App(sys.argv)
30 window = QWidget()
31 
32 btn = Btn(window)
33 btn.setText("按钮")
34 btn.move(100, 100)
35 
36 btn.pressed.connect(lambda: print("I am here"))
37 # 鼠标只要是按下就行,而btn.clicked  鼠标是点击之后又起来
38 
39 
40 window.show()
41 
42 sys.exit(app.exec_())
43 
44 '''
45     输出:
46     <__main__.Btn object at 0x00000150B0261D38> <PyQt5.QtGui.QMouseEvent object at 0x00000150B0261EE8>
47     <PyQt5.QtGui.QMouseEvent object at 0x00000150B0261EE8>
48     请注意我,我不是I am here
49 '''
重写最终的信号发送函数,使得信号没有被发送出去

 

当然,也可以调用父类中的原方法,使其发射出去press 信号:

 1 from PyQt5.Qt import *  # 刚开始学习可以这样一下导入
 2 import sys
 3 
 4 
 5 class App(QApplication):
 6     # def notify(self, QObject, QEvent):  #参数:一个是事件的接收者,一个是 被包装的事件对象
 7     #     pass
 8     QEvent
 9     def notify(self, receiver, event):
10 
11         if receiver.inherits("QPushButton") and event.type() ==  QEvent.MouseButtonPress:
12             print(receiver, event)  #此时 pressed 信号就不会被发出去了
13 
14         return super().notify(receiver, event)
15 
16 
17 class Btn(QPushButton):
18 
19     # def event(self, QEvent):
20 
21     def event(self, event):  # 继续往下分发
22         if event.type() == QEvent.MouseButtonPress:
23             print(event)
24         return super().event(event)   # 继续往下分发
25     def mousePressEvent(self, *args, **kwargs):
26         print("请注意我,我不是I am here")
27         super().mousePressEvent(*args,**kwargs)
28 
29 
30 app = App(sys.argv)
31 window = QWidget()
32 
33 btn = Btn(window)
34 btn.setText("按钮")
35 btn.move(100, 100)
36 
37 btn.pressed.connect(lambda: print("I am here"))
38 # 鼠标只要是按下就行,而btn.clicked  鼠标是点击之后又起来
39 
40 
41 window.show()
42 
43 sys.exit(app.exec_())
44 
45 '''
46     输出:
47     <__main__.Btn object at 0x0000020A212B1D38> <PyQt5.QtGui.QMouseEvent object at 0x0000020A212B1EE8>
48     <PyQt5.QtGui.QMouseEvent object at 0x0000020A212B1EE8>
49     请注意我,我不是I am here
50     I am here
51 '''
让其发射信号

所以,这时相应的槽函数也会正常的起作用了。

到此,我们也知道了一个事件的处理经过了层层分发最后才发送这个信号!

8,QObject 对象之定时器

 它主要的作用是定时,每隔一定的时间去做某件事情。

 

 

 1 from PyQt5.Qt import * #刚开始学习可以这样一下导入
 2 import sys
 3 #1,创建app
 4 app  = QApplication(sys.argv)  
 5 
 6 
 7 #2,控件的操作:
 8 #创建控件
 9 window = QWidget()
10 
11 
12 #设置控件
13 window.setWindowTitle("QObject 之定时器的学习")
14 window.resize(500,500)
15 
16 obj = QObject()
17 
18 timer_id = obj.startTimer(1000)  #这时如果工作就每隔1s调用QObject() 中的timerevent() 方法了
19                                 #所以此时应该重写QObject()中的timerevent() 方法
20 
21 #展示控件
22 window.show()
23 
24 #3,进入消息循环
25 sys.exit(app.exec_())
每隔1s调用QObject类中的timerevent()方法
这时如果工作就每隔1s调用QObject() 中的timerevent() 方法了
所以此时应该重写QObject()中的timerevent() 方法

 

 1 from PyQt5.Qt import * #刚开始学习可以这样一下导入
 2 import sys
 3 
 4 
 5 class MyObject(QObject):
 6     # def timerEvent(self, QTimerEvent):
 7     #     pass
 8     def timerEvent(self, event):
 9         print(event)
10 
11 
12 #1,创建app
13 app  = QApplication(sys.argv)  
14 
15 
16 #2,控件的操作:
17 #创建控件
18 window = QWidget()
19 
20 
21 #设置控件
22 window.setWindowTitle("QObject 之定时器的学习")
23 window.resize(500,500)
24 
25 obj = MyObject()
26 
27 timer_id = obj.startTimer(1000)
28 
29 #展示控件
30 window.show()
31 
32 #3,进入消息循环
33 sys.exit(app.exec_())
34 
35 
36 '''
37     输出: (每隔1s就打印信息)
38     <PyQt5.QtCore.QTimerEvent object at 0x0000025D34B93B88>
39     <PyQt5.QtCore.QTimerEvent object at 0x0000025D34B93B88>
40     <PyQt5.QtCore.QTimerEvent object at 0x0000025D34B93B88>
41     <PyQt5.QtCore.QTimerEvent object at 0x0000025D34B93B88>
42     <PyQt5.QtCore.QTimerEvent object at 0x0000025D34B93B88>
43 '''
重写Object类中的timerevent()方法

如果我们想停止它,将得到的定时器id 传给 killTimer() 即可:

 1 from PyQt5.Qt import * #刚开始学习可以这样一下导入
 2 import sys
 3 
 4 
 5 class MyObject(QObject):
 6     # def timerEvent(self, QTimerEvent):
 7     #     pass
 8     def timerEvent(self, event):
 9         print(event)
10 
11 
12 #1,创建app
13 app  = QApplication(sys.argv)  
14 
15 
16 #2,控件的操作:
17 #创建控件
18 window = QWidget()
19 
20 
21 #设置控件
22 window.setWindowTitle("QObject 之定时器的学习")
23 window.resize(500,500)
24 
25 obj = MyObject()
26 
27 timer_id = obj.startTimer(1000)
28 
29 obj.killTimer(timer_id)
30 
31 #展示控件
32 window.show()
33 
34 #3,进入消息循环
35 sys.exit(app.exec_())
36 
37 
38 '''
39 
40 '''
杀死定时器,此时没有效果

案例一:

 1 from PyQt5.Qt import * #刚开始学习可以这样一下导入
 2 import sys
 3 
 4 
 5 class MyObject(QObject):
 6     # def timerEvent(self, QTimerEvent):
 7     #     pass
 8     def timerEvent(self, event):
 9         print(event)
10 
11 
12 #1,创建app
13 app  = QApplication(sys.argv)  
14 
15 #2,控件的操作:
16 #创建控件
17 window = QWidget()
18 
19 
20 #设置控件
21 window.setWindowTitle("QObject 之定时器的学习")
22 window.resize(500,500)
23 
24 label = QLabel(window)
25 label.setText("10")
26 label.setStyleSheet("font-size:22px;")
27 label.move(200,200)
28 
29 
30 #展示控件
31 window.show()
32 
33 #3,进入消息循环
34 sys.exit(app.exec_())
35 
36 
37 '''
38 
39 '''
ui界面

下面实现核心功能,倒计时:

 1 from PyQt5.Qt import * #刚开始学习可以这样一下导入
 2 import sys
 3 
 4 #1,创建app
 5 app  = QApplication(sys.argv)  
 6 
 7 #2,控件的操作:
 8 #创建控件
 9 window = QWidget()
10 
11 
12 #设置控件
13 window.setWindowTitle("QObject 之定时器的学习")
14 window.resize(500,500)
15 
16 label = QLabel(window)
17 label.setText("10")
18 label.setStyleSheet("font-size:22px;")
19 label.move(200,200)
20 
21 
22 label.startTimer(1000)  # 因为label 肯定是继承QObject 的,所以肯定有starttimer方法。
23                             # 此时要想真正工作还是要重写QLabel类中的timerEvent()方法
24 
25 
26 #展示控件
27 window.show()
28 
29 #3,进入消息循环
30 sys.exit(app.exec_())
31 
32 
33 '''
34 '''
第一阶段
 1 from PyQt5.Qt import * #刚开始学习可以这样一下导入
 2 import sys
 3 
 4 class MyLabel(QLabel):
 5     def timerEvent(self, *args, **kwargs):
 6         print("python")
 7 
 8 
 9 #1,创建app
10 app  = QApplication(sys.argv)  
11 
12 #2,控件的操作:
13 #创建控件
14 window = QWidget()
15 
16 
17 #设置控件
18 window.setWindowTitle("QObject 之定时器的学习")
19 window.resize(500,500)
20 
21 label = MyLabel(window)
22 label.setText("10")
23 label.setStyleSheet("font-size:22px;")
24 label.move(200,200)
25 
26 
27 timer_id = label.startTimer(1000)  # 因为label 肯定是继承QObject 的,所以肯定有starttimer方法。
28                             # 此时要想真正工作还是要重写QLabel类中的timerEvent()方法
29 
30 
31 #展示控件
32 window.show()
33 
34 #3,进入消息循环
35 sys.exit(app.exec_())
36 
37 
38 '''
39 python
40 python
41 python
42 '''
第二阶段:每隔一秒打印python
 1 from PyQt5.Qt import * #刚开始学习可以这样一下导入
 2 import sys
 3 
 4 class MyLabel(QLabel):
 5     def timerEvent(self, *args, **kwargs):
 6         print("python",)
 7         #1,获取当前的标签内容
 8         current_sec = int(self.text())
 9         current_sec -=1
10         self.setText(str(current_sec))
11 
12 
13 
14 #1,创建app
15 app  = QApplication(sys.argv)  
16 
17 #2,控件的操作:
18 #创建控件
19 window = QWidget()
20 
21 
22 #设置控件
23 window.setWindowTitle("QObject 之定时器的学习")
24 window.resize(500,500)
25 
26 label = MyLabel(window)
27 label.setText("10")
28 label.setStyleSheet("font-size:22px;")
29 label.move(200,200)
30 
31 
32 timer_id = label.startTimer(1000)  # 因为label 肯定是继承QObject 的,所以肯定有starttimer方法。
33                             # 此时要想真正工作还是要重写QLabel类中的timerEvent()方法
34 
35 
36 
37 #展示控件
38 window.show()
39 
40 #3,进入消息循环
41 sys.exit(app.exec_())
42 
43 
44 '''
45 python
46 python
47 python
48 python
49 python
50 python
51 python
52 python
53 python
54 python
55 python
56 python
57 python
58 '''
此时会出现负数情况,这主要是我们在其内部无法关闭定时器,timer_id 传不进去

解决方法是,我们的类都定义了,所以可以将所有用到的方法直接都重写就完了!

 1 from PyQt5.Qt import * #刚开始学习可以这样一下导入
 2 import sys
 3 
 4 class MyLabel(QLabel):
 5 
 6     def __init__(self,*args,**kwargs):  # 这更加通用
 7         super().__init__(*args,**kwargs)
 8         self.setText("10")
 9         self.setStyleSheet("font-size:22px;")
10         self.move(200,200)
11         self.timer_id = self.startTimer(1000)
12 
13 
14     def timerEvent(self, *args, **kwargs):
15         print("python",)
16         #1,获取当前的标签内容
17         current_sec = int(self.text())
18         current_sec -=1
19         self.setText(str(current_sec))
20         if current_sec == 0:
21             self.killTimer(self.timer_id)
22 
23 
24 #1,创建app
25 app  = QApplication(sys.argv)  
26 
27 #2,控件的操作:
28 #创建控件
29 window = QWidget()
30 
31 
32 #设置控件
33 window.setWindowTitle("QObject 之定时器的学习")
34 window.resize(500,500)
35 
36 label = MyLabel(window)
37 
38 
39 #展示控件
40 window.show()
41 
42 #3,进入消息循环
43 sys.exit(app.exec_())
44 
45 
46 '''
47 python
48 python
49 python
50 python
51 python
52 python
53 python
54 python
55 python
56 python
57 '''
解决负数问题

但是,此时也有问题,封装的太狠了,所以导致灵活性下降!

比如,说现在想将倒计时改为20s,肯定要在类中修改。

此时,也可以通过增加对外的接口来增加类的灵活性。

 1 from PyQt5.Qt import * #刚开始学习可以这样一下导入
 2 import sys
 3 
 4 class MyLabel(QLabel):
 5 
 6     def __init__(self,*args,**kwargs):  # 这更加通用
 7         super().__init__(*args,**kwargs)
 8         self.setStyleSheet("font-size:22px;")
 9         self.move(200,200)
10 
11 
12     def setSec(self,sec):
13         self.setText(str(sec))
14 
15     def startMyTimer(self,ms):
16          self.timer_id = self.startTimer(ms)
17 
18     def timerEvent(self, *args, **kwargs):
19         print("python",)
20         #1,获取当前的标签内容
21         current_sec = int(self.text())
22         current_sec -=1
23         self.setText(str(current_sec))
24         if current_sec == 0:
25             self.killTimer(self.timer_id)
26 
27 
28 #1,创建app
29 app  = QApplication(sys.argv)  
30 
31 #2,控件的操作:
32 #创建控件
33 window = QWidget()
34 
35 
36 #设置控件
37 window.setWindowTitle("QObject 之定时器的学习")
38 window.resize(500,500)
39 
40 label = MyLabel(window)
41 label.setSec(5)
42 
43 label.startMyTimer(500)
44 
45 #展示控件
46 window.show()
47 
48 #3,进入消息循环
49 sys.exit(app.exec_())
50 
51 
52 '''
53 python
54 python
55 python
56 python
57 python
58 '''
通过提供接口更加灵活

所以,封装一个控件的时候,要同时注意它的封装性和灵活性,不能过度封装!

 案例二

 

 1 from PyQt5.Qt import * #刚开始学习可以这样一下导入
 2 import sys
 3 
 4 
 5 class MyWidget(QWidget):
 6     def timerEvent(self, *args, **kwargs):
 7         print("python")
 8         current_w = self.width()
 9         current_h = self.height()
10 
11         self.resize(current_w+10,current_h+10)
12 
13 #1,创建app
14 app  = QApplication(sys.argv)
15 
16 
17 #2,控件的操作:
18 #创建控件
19 window = MyWidget()
20 
21 window.startTimer(100)  #每隔100ms 调用一次 timerEvent
22 
23 
24 #设置控件
25 window.setWindowTitle("Qt 定时器案例")
26 window.resize(500,500)
27 
28 
29 
30 
31 
32 #展示控件
33 window.show()
34 
35 #3,进入消息循环
36 sys.exit(app.exec_())
案例二:

注:这里也可以对其进行封装,只是这里没有弄而已!

 

总结:到此,QObject 中所有的功能都弄完了,下面的是QWidget(按继承图来的!)

QWidget学习见: https://www.cnblogs.com/zach0812/p/11347306.html

 

posted @ 2019-08-13 17:12  Zcb0812  阅读(2699)  评论(0编辑  收藏  举报