创建一个窗口
1.1 面向过程版本代码
- 代码示例
from PyQt5.Qt import *
import sys
app=QApplication(sys.argv)
window=QWidget()
window.setWindowTitle('我的第一个窗体')
window.resize(500,500)
window.move(400,200)
label=QLabel(window)
label.setText('Hello World!')
label.move(200,200)
window.show()
sys.exit(app.exec_())
- 运行结果:
- 代码说明:
# 0.导入需要的包和模块
from PyQt5.Qt import * # 主要包含了我们常用的一些类
import sys
# sys.argv:当别人通过命令行启动这个程序的时候,可以设定一种功能(接收命令行传递的参数,来执行不同的业务逻辑
# 1.创建一个应用程序
app=QApplication(sys.argv)
# 2.控件的操作(创建控件,设置控件大小、位置、样式,事件,信号的处理...)
# 2.1 创建一个窗口
"""
当我们创建一个控件之后,如果说,这个控件没有父控件,
则把它当作是顶层控件(窗口),系统会自动给这个窗口添加一些装饰(标题栏),
窗口控件具备一些特性(设置标题、图标)
"""
window=QWidget()
# 设置窗口标题
window.setWindowTitle('我的第一个窗体')
# 设置窗口大小
window.resize(500,500)
# 设置窗口位置
window.move(400,200)
# 2.2 设置控件
# 控件也可以作为一个容器(承载其他的控件)
# 设置一个标签,展示在窗口内部
label=QLabel(window) # 注意传参window,否则label不会出现在窗口上
# 设置标签里的内容
label.setText('Hello World!')
# 设置位置
label.move(200,200)
# 2.3 展示窗口
# 刚创建好一个控件后,(这个控件没有什么父控件),默认情况下不会被展示,只有手动show一下
# 如果这个控件,有父控件的,那么一般情况下,父控件展示后,子控件会自动展示
window.show()
# 3.应用程序的执行,进入到消息循环(无限循环),否则窗口就会show一次之后消失
# 检测到整个程序所接收到的用户的交互信息
sys.exit(app.exec_()) # 退出码,0表示正常退出(自动结束或用户手动关闭),非0表示异常退出
1.2 面向对象版本代码
- 代码示例
from PyQt5.Qt import *
import sys
class Window(QWidget):#继承QWidget类
# 重写父类__init__方法
def __init__(self):
# 重用父类的__init__方法
super().__init__()
self.setWindowTitle('面向对象创建窗体')
self.resize(500, 500)
#添加子控件
def setup_ui(self):
label = QLabel(self)
label.setText('点击点击...')
if __name__=='__main__':
app=QApplication(sys.argv)
window=Window()
window.setup_ui()
window.show()
sys.exit(app.exec_())
- 运行结果:
- 面向过程的缺点:
- 代码冗余量大
- 修改某控件查找麻烦
- 面向对象继承的提出
- 创建面向对象不能瞎改原本的类,可以考虑通过继承来实现
# 0.导入包和模块
from PyQt5.Qt import *
import sys
# 继承类、定义自己的方法
class Window(QWidget):
def __init__(self):
print("继承类")
# 1.创建应用程序对象
app = QApplication(sys.argv)
# 2.1 创建控件
window = Window()
# 2.2 设置控件
window.setWindowTitle("用了继承类")
window.resize(500, 500)
# 2.3 展示控件
window.show()
# 3.进入消息循环
sys.exit(app.exec_())
- 运行报错:父类的 init() 方法没有被调用
- 错误原因:当我们用 window = QWidget() 方法去创建控件时,会自动调用系统提供给我们的 QWidget 的 init 方法。但在继承过程中,重新写了 init 方法,导致创建对象时,会自动先调用子类 init 方法,而子类 init 方法没有调用父类 init 方法里的准备操作。
- 解决方法:在子类的 init 方法里首先调用父类的 init 方法,即不是替换而是在原基础上增加自己的配置。修改后的类继承如下:
# 0.导入包和模块
from PyQt5.Qt import *
import sys
# 继承类、定义自己的方法
class Window(QWidget):
def __init__(self):
# super后自动补全后面的内容
super(Window, self).__init__()
print("继承类")
# 1.创建应用程序对象
app = QApplication(sys.argv)
# 2.1 创建控件
window = Window()
# 2.2 设置控件
window.setWindowTitle("用了继承类")
window.resize(500, 500)
# 2.3 展示控件
window.show()
# 3.进入消息循环
sys.exit(app.exec_())
- 运行结果:
- 输出了”继承类“这三个字还有原来那个窗口。
- 同理,可以把菜单栏的控件相关配置全都塞到继承类里面去(就像 print 语句)。
- 类的封装
- self:通过 Window 类创建出来的实例对象
# 继承类、定义自己的方法
class Window(QWidget):
def __init__(self):
super(Window, self).__init__()
self.setWindowTitle("面向对象")
self.resize(500, 500)
label = QLabel(self)
label.setText("标签签")
- 把子控件的添加单独列到一个方法里面去
# 继承类、定义自己的方法
class Window(QWidget):
# 初始化
def __init__(self):
super(Window, self).__init__()
self.setWindowTitle("面向对象")
self.resize(500, 500)
self.setup_ui()
# 存放所有子控件以及子控件的配置操作
def setup_ui(self):
label = QLabel(self)
label.setText("标签签")
- 从功能层面与刚刚的写法并无区别,但从结构来说这个更清晰。
- 再进一步,把导入的包和继承的类放在另一个 python 文件 Menu.py (注意该文件名称得是英语)中,然后如下一句话就可以导入类。
from Menu import Window
- 这样,通过类增强了代码的可维护性,有问题直接改这个类,其他地方统统不需要动。
- 类的测试
- 如果需要去测试类的功能是否正常,直接在 Menu.py 文件中加上测试代码就行。
import sys
app = QApplication(sys.argv)
window = Window()
window.show()
sys.exit(app.exec_())
- 但该测试部分在被导入时是不需要执行的,这时候就用到了
if __name__ == '__main__':
它帮助我们的测试代码只有在右键运行时才会执行,而在被导入其他 python 文件时不需要执行