一、介绍

PyQt基于QT库的python封装,是一个图形用户界面(GUI)工具包,允许用户使用python语言创建桌面应用程序。目前,不同版本中,PyQt5是较为流行的版本,支持python 2.7 和 python 3.x 。

PyQt支持两种开发方式,可视化和编程化。

- 编程式创建界面无需多说,pip安装成功以后,有较深基础功底的可直接上手编码。
- 可视化方式对新手非常友好,用户可基于Qt Designe工具包进行组件拖拽、布局管理等操作。

 上述图片来自[Python GUI PyQt] PyQt5快速入门_python 如何使用pyqt5-CSDN博客博主的文章


————————————————

二、安装

在我们自己的python虚拟环境中,pip安装依赖包PyQt5, pyqt5_tools
pyqt5_tools 包含一些辅助 PyQt5 的开发工具,其中就有我们要用的 Qt Designer

1 pip install PyQt5 PyQt5-tools -i https://pypi.tuna.tsinghua.edu.cn/simple
2 
3 可以带上国内的镜像源,会快一点,也不会报错

安装成功以后,win+R 搜索"designer",出现图标表示成功。

 

2.2 Pycharm配置

python语言开发,大部分使用Pycharm集成开发工具,这里在Pycharm工具中配置QT designer外部工具,在工程开发中让界面设计和解析变得容易。

打开Pycharm,File -> Settings ->Tools -> External Tools,点击加号添加,Program我这里添加的是安装包路径,因为我安装了PyQt_tools,找不到designer。Working directory设置保存ui文件的文件,$FileDir$表示当前文件所在目录

新接触该模块,相关该模块的部分文章中提到designer.exe的文件夹位置大多都找不到,可能原因是版本更新。现提供该文件的位置。

(基本上都在自己python环境下Lib文件夹中)我是用conda创建的虚拟环境,所以我要一层一层找下去,查找方式基本上都一样

C:\Users\19225\.conda\envs\dev_env\Lib\site-packages\qt5_applications\Qt\bin\designer.exe

 

 添加 PyUIC 工具

1 在 CreateTool 窗口依次填写:
2 
3 Name:填写 “PyUIC”
4 Program:填写 python.exe 的路径
5 注意:此处填写 IDE 使用的 Python Interpreter的路径。如果小白的 Python 或 Anaconda3 安装在其他路径下,或者选择其它路径中的 python.exe 作为 Python Interpreter,可以从 Pycharm -> Settings -> Project -> Python Interpreter 打开配置窗口,从右侧上方 “Python Interpreter:” 选项框找到 python.exe 的路径。
6 
7 
8 Working directory:填写将 .ui 文件转换为 .py 文件的保存路径
9 例如,要将 .py 文件保存在当前 Project 的路径下,则填写 “$FileDir$”。

 

配置Pyrcc

 

1 Program:python的安装目录下的Scripts文件夹的pyrcc5.exe文件
2 Arguments:$FileName$ -o $FileNameWithoutExtension$_rc.py

ui转py的过程:

选中文件,鼠标右击,打开扩展,选择PyUIC,它会生成.py文件

将.ui文件转化为.py文件的命令行方法:
1 python -m PyQt5.uic.pyuic demo.ui -o demo.py

 

————————————————

三、界面设计介绍

打开外部工具,会弹出窗口提示,如果不想每次启动都弹,在该窗口左下角设置去掉即可。

先整体认识下designer工具,左侧是不同类型组件,右侧可查看ui结构以及设置每个组件的属性,中间灰色地带为画布。

 

3.1 组件

组件是构建图像界面基本的模块,pyqt提供了多种组件,这里介绍一些使用频率较高的组件

 

 

PyQt5的常用基本控件

 

3.1.1 菜单类组件

菜单栏组件包含 菜单栏+状态栏+工具栏 三部分

在designer中,先创建一个主窗口, 文件->新建->Main Window

查看主窗口右侧ui结构,自带的菜单栏,状态栏,缺少工具栏ToolBar,选中MainWindow右击添加

 

 

四.PyQt基本UI

1 只要是Qt制作的app,必须有且只有1个QApplication对象
2 sys.argv当作参数的目的是将运行时的命令参数传递给QApplication对象
3 创建了一个QWidget对象(这是一个白框),将它的标题设置为”第一个”PyQt“
4 然后调用show方法显示出来
5 开始运行程序,直到关闭了窗口,这里相当于是一个while(True)的循环等待机制,异步的

 

 另外一种运行脚本方式:

1 python 文件名.py

 

4.1.PyQt资料查询方式​

PyQt中有非常多的功能模块,开发中最常用的功能模块主要有三个:

QtCore:包含了核心的非GUI的功能。主要和时间、文件与文件夹、各种数据、流、URLs、mime类文件、进程与线程一起使用
QtGui:包含了窗口系统、事件处理、2D图像、基本绘画、字体和文字类
QtWidgets:包含了一些列创建桌面应用的UI元素
​ 可以参考PyQt官网的所有模块,地址:https://www.riverbankcomputing.com/static/Docs/PyQt5/module_index.html#ref-module-index
————————————————

4.2.控件

1.按钮

​ 按钮对应的控件名称为QPushButton,位于PyQt5.QtWidgets里面:

 1 import sys
 2 from PyQt5.QtWidgets import QApplication, QWidget, QPushButton
 3 
 4 if __name__ == '__main__':
 5     app = QApplication(sys.argv)
 6     w = QWidget()
 7     # 设置窗口标题
 8     w.setWindowTitle("第一个PyQt")
 9     # 在窗口里面添加控件
10     btn = QPushButton("按钮")
11     # 设置按钮的父亲是当前窗口,等于是添加到窗口中显示
12     btn.setParent(w)
13     # 展示窗口
14     w.show()
15     # 程序进行循环等待状态
16     app.exec()
2.文本

​ 纯文本控件名称为QLabel,位于PyQt5.QtWidgets里面,纯文本控件仅仅作为标识显示而已,类似输入内容前的一段标签提示(账号、密码)

3.调整窗口
 1 import sys
 2 from PyQt5.QtWidgets import QApplication, QWidget, QPushButton, QLabel, QLineEdit, QDesktopWidget
 3 
 4 if __name__ == '__main__':
 5     app = QApplication(sys.argv)
 6     w = QWidget()
 7     # 设置窗口标题
 8     w.setWindowTitle("第一个PyQt")
 9     # 设置窗口大小
10     w.resize(300, 300)
11     # 调整窗口在屏幕的中央显示
12     center_pointer = QDesktopWidget().availableGeometry().center()
13     x = center_pointer.x()
14     y = center_pointer.y()
15     old_x, old_y, width, height = w.frameGeometry().getRect()
16     w.move(int(x - width / 2), int(y - height / 2))
17     w.show()
18     app.exec_()

 

 

4.设置窗口的图标

 

 

五.布局

1 在Qt里面布局分为四个大类:
2 
3 QBoxLayout:盒子布局,一般使用它的两个子类QHBoxLayout和QVBoxLayout负责水平和垂直布局。
4 
5 QGridLayout: 网格布局,有的人称之为九宫格布局
6 
7 QFormLayout:用于提交数据form表单。比如:登录,注册类似的场景
8 
9 QStackedLayout:多页面切换的布局,一次只能看到一个界面。这个布局叫做抽屉布局

=========================================布局布好以后,右键布局---打破布局,然后就好啦

 

 

5.1.QBoxLayout垂直布局实例

 1 import sys
 2 from PyQt5.QtWidgets import QApplication, QVBoxLayout, QWidget, QPushButton, QGroupBox, QMainWindow
 3 
 4 
 5 class MyWindow(QWidget):
 6     def __init__(self):
 7         # 切记一定要调用父类的__init__方法,因为它里面有很多对UI空间的初始化操作
 8         super().__init__()
 9         # 设置大小
10         self.resize(300, 300)
11         # 设置标题
12         self.setWindowTitle("垂直布局")
13         # 创建一个垂直布局器
14         layout = QVBoxLayout()
15         # 作用是在布局器中增加一个伸缩量,里面的参数表示QSpacerItem的个数,默认值为零
16         # 会将你放在layout中的空间压缩成默认的大小
17         layout.addStretch(1)
18         # 按钮1,这里没有设置父对象
19         btn1 = QPushButton("按钮1")
20         # 添加到布局器中
21         # 不设置父对象而是直接设置布局器
22         layout.addWidget(btn1)
23         layout.addStretch(1)
24         # 按钮2
25         btn2 = QPushButton("按钮2")
26         # 添加到布局器
27         layout.addWidget(btn2)
28         layout.addStretch(1)
29         # 按钮3
30         btn3 = QPushButton("按钮3")
31         # 添加到布局器
32         layout.addWidget(btn3)
33         layout.addStretch(2)
34         # 让当前的窗口使用这个布局器来排列
35         self.setLayout(layout)
36 
37 
38 if __name__ == '__main__':
39     app = QApplication(sys.argv)
40     # 创建一个QWidget子类
41     w = MyWindow()
42     w.show()
43     app.exec()

 

 5.1.1水平布局的代码如下

​ 这里我们将垂直布局与水平布局综合到一起,但是一个Widget只能设置一个布局器,如何解决呢?通过布局器的嵌套,一个大的布局器中嵌套两个小的布局器,一个垂直一个水平。

 1 import sys
 2 from PyQt5.QtWidgets import QApplication, QWidget, QGroupBox, QVBoxLayout, QHBoxLayout, QRadioButton
 3 
 4 
 5 class MyWindow(QWidget):
 6     def __init__(self):
 7         super().__init__()
 8         self.init_ui()
 9 
10     def init_ui(self):
11         # 最外层的垂直布局,包含两部分:爱好和性别
12         container = QVBoxLayout()
13         # -----创建第1个组,添加多个组件-----
14         # hobby 主要是保证他们是一个组。
15         hobby_box = QGroupBox("爱好")
16         # v_layout 保证三个爱好是垂直摆放
17         v_layout = QVBoxLayout()
18         btn1 = QRadioButton("抽烟")
19         btn2 = QRadioButton("喝酒")
20         btn3 = QRadioButton("烫头")
21         # 添加到v_layout中
22         v_layout.addWidget(btn1)
23         v_layout.addWidget(btn2)
24         v_layout.addWidget(btn3)
25         # 把v_layout添加到hobby_box中
26         hobby_box.setLayout(v_layout)
27         # -----创建第2个组,添加多个组件-----
28         # 性别组
29         gender_box = QGroupBox("性别")
30         # 性别容器
31         h_layout = QHBoxLayout()
32         # 性别选项
33         btn4 = QRadioButton("")
34         btn5 = QRadioButton("")
35         # 追加到性别容器中
36         h_layout.addWidget(btn4)
37         h_layout.addWidget(btn5)
38         # 添加到 box中
39         gender_box.setLayout(h_layout)
40         # 把爱好的内容添加到容器中
41         container.addWidget(hobby_box)
42         # 把性别的内容添加到容器中
43         container.addWidget(gender_box)
44         # 设置窗口显示的内容是最外层容器
45         self.setLayout(container)
46 
47 
48 if __name__ == '__main__':
49     app = QApplication(sys.argv)
50     w = MyWindow()
51     w.show()
52     app.exec()

 

5.2.QGridLayout

 1 import sys
 2 from PyQt5.QtWidgets import QApplication, QWidget, QVBoxLayout, QPushButton, QLineEdit, QGridLayout
 3 
 4 
 5 class MyWindow(QWidget):
 6 
 7     def __init__(self):
 8         super().__init__()
 9         self.init_ui()
10 
11     def init_ui(self):
12         self.setWindowTitle("计算器")
13         # 准备数据
14         data = {
15             0: ["7", "8", "9", "+", "("],
16             1: ["4", "5", "6", "-", ")"],
17             2: ["1", "2", "3", "*", "<-"],
18             3: ["0", ".", "=", "/", "C"]
19         }
20         # 整体垂直布局
21         layout = QVBoxLayout()
22         # 输入框
23         edit = QLineEdit()
24         edit.setPlaceholderText("请输入内容")
25         # 把输入框添加到容器中
26         layout.addWidget(edit)
27         # 网格布局
28         grid = QGridLayout()
29         # 循环创建追加进去
30         for line_number, line_data in data.items():
31             # 此时line_number是第几行,line_data是当前行的数据
32             for col_number, number in enumerate(line_data):
33                 # 此时col_number是第几列,number是要显示的符号
34                 btn = QPushButton(number)
35                 # grid.addWidget(btn)
36                 grid.addWidget(btn, line_number, col_number)
37         # 把网格布局追加到容器中
38         layout.addLayout(grid)
39         self.setLayout(layout)
40 
41 
42 if __name__ == '__main__':
43     app = QApplication(sys.argv)
44     w = MyWindow()
45     w.show()
46     app.exec()

 

5.3.QFormLayout

 1 import sys
 2 from PyQt5.QtCore import Qt
 3 from PyQt5.QtWidgets import QVBoxLayout, QFormLayout, QLineEdit, QPushButton, QApplication, QWidget
 4 
 5 
 6 class MyWindow(QWidget):
 7     def __init__(self):
 8         super().__init__()
 9         self.init_ui()
10 
11     def init_ui(self):
12         # 设定当前Widget的宽高(可以拉伸大小)
13         # self.resize(300, 200)
14         # 禁止改变宽高(不可以拉伸)
15         self.setFixedSize(300, 150)
16         # 外层容器
17         container = QVBoxLayout()
18         # 表单容器
19         form_layout = QFormLayout()
20         # 创建1个输入框
21         edit = QLineEdit()
22         edit.setPlaceholderText("请输入账号")
23         form_layout.addRow("账号:", edit)
24         # 创建另外1个输入框
25         edit2 = QLineEdit()
26         edit2.setPlaceholderText("请输入密码")
27         form_layout.addRow("密码:", edit2)
28         # 将from_layout添加到垂直布局器中
29         container.addLayout(form_layout)
30         # 按钮
31         login_btn = QPushButton("登录")
32         login_btn.setFixedSize(100, 30)
33         # 把按钮添加到容器中,并且指定它的对齐方式
34         container.addWidget(login_btn, alignment=Qt.AlignRight)
35         # 设置当前Widget的布局器,从而显示这个布局器中的子控件
36         self.setLayout(container)
37 
38 
39 if __name__ == '__main__':
40     app = QApplication(sys.argv)
41     w = MyWindow()
42     w.show()
43     app.exec()

 

5.4.QStackedLayout

 1 import sys
 2 from PyQt5.QtWidgets import QApplication, QWidget, QVBoxLayout, QPushButton, QStackedLayout, QLabel
 3 
 4 
 5 class Window1(QWidget):
 6     def __init__(self):
 7         super().__init__()
 8         QLabel("我是抽屉1要显示的内容", self)
 9         self.setStyleSheet("background-color:green;")
10 
11 
12 class Window2(QWidget):
13     def __init__(self):
14         super().__init__()
15         QLabel("我是抽屉2要显示的内容", self)
16         self.setStyleSheet("background-color:red;")
17 
18 
19 class MyWindow(QWidget):
20     def __init__(self, parent=None):
21         super().__init__(parent)
22         self.create_stacked_layout()
23         self.init_ui()
24 
25     def create_stacked_layout(self):
26         # 创建堆叠(抽屉)布局
27         self.stacked_layout = QStackedLayout()
28         # 创建单独的Widget
29         win1 = Window1()
30         win2 = Window2()
31         # 将创建的2个Widget添加到抽屉布局器中
32         self.stacked_layout.addWidget(win1)
33         self.stacked_layout.addWidget(win2)
34 
35     def init_ui(self):
36         # 设置Widget大小以及固定宽高
37         self.setFixedSize(300, 270)
38         # 1. 创建整体的布局器
39         container = QVBoxLayout()
40         # 2. 创建1个要显示具体内容的子Widget
41         widget = QWidget()
42         widget.setLayout(self.stacked_layout)
43         widget.setStyleSheet("background-color:grey;")
44         # 3. 创建2个按钮,用来点击进行切换抽屉布局器中的Widget
45         btn_press1 = QPushButton("抽屉1")
46         btn_press2 = QPushButton("抽屉2")
47         # 给按钮添加事件(即点击后要调用的函数)
48         btn_press1.clicked.connect(self.btn_press1_clicked)
49         btn_press2.clicked.connect(self.btn_press2_clicked)
50         # 4. 将需要显示的空间添加到布局器中
51         container.addWidget(widget)
52         container.addWidget(btn_press1)
53         container.addWidget(btn_press2)
54         # 5. 设置当前要显示的Widget,从而能够显示这个布局器中的控件
55         self.setLayout(container)
56 
57     def btn_press1_clicked(self):
58         # 设置抽屉布局器的当前索引值,即可切换显示哪个Widget
59         self.stacked_layout.setCurrentIndex(0)
60 
61     def btn_press2_clicked(self):
62         # 设置抽屉布局器的当前索引值,即可切换显示哪个Widget
63         self.stacked_layout.setCurrentIndex(1)
64 
65 
66 if __name__ == "__main__":
67     app = QApplication(sys.argv)
68     win = MyWindow()
69     win.show()
70     app.exec()

      

 

上述关于布局还有一种简单的方法:

(1)先移组件,再布局。

放置五个按钮,让这五个按钮等宽的,随便排列

(全部选中–>鼠标右键–>布局–>水平布局 预览)

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 
posted on 2024-09-03 15:46  认真的六六  阅读(76)  评论(0编辑  收藏  举报