『pyqt5 从0基础开始项目实战』02. 页面布局设计(保姆级图文)
欢迎关注 『pyqt5 从0基础开始项目实战』 专栏,持续更新中
欢迎关注 『pyqt5 从0基础开始项目实战』 专栏,持续更新中
弹性布局介绍
当然你也可以用可视化工具designer设计ui然后转为为py文件,本专栏注重学习基础,就不再做这方面的介绍了。
并不是采用安卓开发中的绝对定位布局(画坐标系,按照x,y坐标布局,这样很容易因为空间的大小造成重叠控件等问题)
一般设计思路是首先窗口整体是垂直布局,然后每一行是水平布局,在每一行内部通过空白占位的弹簧设置各个控件的位置。
导包和框架代码
在上一文的基础框架上加入了本节需要用到的包
import sys
from PyQt5.QtCore import Qt
from PyQt5.QtWidgets import QApplication, QWidget, QDesktopWidget, QHBoxLayout, QVBoxLayout
from PyQt5.QtWidgets import QPushButton, QLineEdit, QTableWidget, QTableWidgetItem, QLabelclass MainWindow(QWidget):def __init__(self):# 用super 继承父类的初始化super().__init__()# 设置窗口的窗体标题self.setWindowTitle('发现你走远了的xx系统')# 设置窗体的尺寸self.resize(1000, 450)# 设置窗体位置#获取整个窗口部分的宽高和左上角坐标信息,返回值是一个QRect类型,(x,y width,height)qr = self.frameGeometry()cp = QDesktopWidget().availableGeometry().center()#得到屏幕中间的位置信息qr.moveCenter(cp)#让我们的窗体移动到屏幕中间if __name__ == '__main__':app = QApplication(sys.argv)#实例化一个Application应用,所有的窗口均在其下运行window = MainWindow() # 实例化窗口对象window.show() # 窗口展示sys.exit(app.exec_())# app.exec_()运行主循环,并在退出时返回状态代码。# sys.exit(n)退出您的应用程序并返回n到父进程(通常是您的shell)
布局框架搭建
我们的窗口布局下有4个部分的子布局
1. 总体布局框架
# 创建窗口总布局layout = QVBoxLayout()# 1.顶部菜单布局header_layout = QHBoxLayout() # 创建顶部菜单布局layout.addLayout(header_layout) # 将顶部菜单布局添加到总布局# 2.添加内容布局form_layout = QHBoxLayout() # 创建添加内容布局layout.addLayout(form_layout) # 将添加内容布局添加到总布局# 3.表格数据展示布局table_layout = QHBoxLayout()layout.addLayout(table_layout)# 4.底部菜单footer_layout = QHBoxLayout()layout.addLayout(footer_layout)# 给窗体设置元素的排列方式self.setLayout(layout)
- 不要忘记最后给窗体设置元素的排列方式(不然布局不会生效,我一开始学找了半天的bug······)
- self.setLayout(layout)
2. 顶部菜单布局
顶部菜单布局代码修改为:
# 1.顶部菜单布局header_layout = QHBoxLayout() # 创建顶部菜单布局# 1.1 放入按钮btn_start =QPushButton("开始")#新建一个开始按钮header_layout.addWidget(btn_start)#将开始按钮添加到顶部菜单布局btn_stop =QPushButton("停止")#新建一个开始按钮header_layout.addWidget(btn_stop)#将开始按钮添加到顶部菜单布局# 1.2 加入弹簧header_layout.addStretch()layout.addLayout(header_layout) # 将顶部菜单布局添加到总布局
3. form添加内容布局
# 2.添加内容布局form_layout = QHBoxLayout() # 创建添加内容布局# 2.1 输入框txt_asin=QLineEdit()#新建一个输入框对象txt_asin.setText("B07YN82X3B=100")#设置默认的form数据txt_asin.setPlaceholderText("请输入商品ID和价格,例如:B0818JJQQ8=88")#设置灰色的提示信息form_layout.addWidget(txt_asin)#将输入框加入到布局中# 2.2 添加按钮btn_add = QPushButton("添加")#新建一个添加按钮form_layout.addWidget(btn_add)#将添加按钮添加到form布局layout.addLayout(form_layout) # 将添加内容布局添加到总布局
4. table数据展示布局
因为表格比较多,修改一下前文提到的窗体尺寸
# 窗体的尺寸self.resize(1228, 450)
- 给表格添加单个行索引或者列索引的值
# 3.表格数据展示布局table_layout = QHBoxLayout()# 3.1 创建表格table_widget=QTableWidget(2,8)#新建一个2行8列的表格# 修改表格索引名item=QTableWidgetItem()item.setText("标题0")table_widget.setHorizontalHeaderItem(0,item)table_widget.setColumnWidth(0,150)#设置水平单元格0号位置的宽度 150item2=QTableWidgetItem()item2.setText("网址1")table_widget.setHorizontalHeaderItem(1,item2)table_widget.setColumnWidth(1,400)#设置水平单元格1号位置的宽度 400item3=QTableWidgetItem()item3.setText("行索引0")table_widget.setVerticalHeaderItem(0,item3)table_layout.addWidget(table_widget)#把表格添加到表格布局中layout.addLayout(table_layout)
-
给表格批量添加行索引 列索引的值,通过字典键值对和循环实现,不会用enumerate循环的话也可以用for循环代替
-
注意新建表格的时候,因为没有数据,所以新建0行的表格
# 3.表格数据展示布局table_layout = QHBoxLayout()# 3.1 创建表格table_widget=QTableWidget(0,8)#新建一个0行2列的表格table_header = [{"field": "asin", "text": "ASIN", 'width': 120},{"field": "title", "text": "标题", 'width': 150},{"field": "url", "text": "URL", 'width': 400},{"field": "price", "text": "底价", 'width': 100},{"field": "success", "text": "成功次数", 'width': 100},{"field": "error", "text": "503次数", 'width': 100},{"field": "status", "text": "状态", 'width': 100},{"field": "frequency", "text": "频率(N秒/次)", 'width': 100},]for idx,info in enumerate(table_header):item=QTableWidgetItem()item.setText(info['text'])table_widget.setHorizontalHeaderItem(idx,item)table_widget.setColumnWidth(idx,info['width'])table_layout.addWidget(table_widget)#把表格添加到表格布局中layout.addLayout(table_layout)
5. footer底部菜单
# 4.底部菜单footer_layout = QHBoxLayout()label_status = QLabel("未检测", self)footer_layout.addWidget(label_status)footer_layout.addStretch()#添加弹簧,更加美观btn_reset = QPushButton("重新初始化")footer_layout.addWidget(btn_reset)btn_recheck = QPushButton("重新检测")footer_layout.addWidget(btn_recheck)btn_reset_count = QPushButton("次数清零")footer_layout.addWidget(btn_reset_count)btn_delete = QPushButton("删除检测项")footer_layout.addWidget(btn_delete)btn_alert = QPushButton("SMTP报警配置")footer_layout.addWidget(btn_alert)btn_proxy = QPushButton("代理IP")footer_layout.addWidget(btn_proxy)layout.addLayout(footer_layout)
我们在没有新增弹簧时,所有的按钮平均宽度。
新增宽度后,按钮会自适应文本内容,相对而言更加美观
完整项目代码
import os
import sys
from PyQt5.QtCore import Qt
from PyQt5.QtWidgets import QApplication, QWidget, QDesktopWidget, QHBoxLayout, QVBoxLayout
from PyQt5.QtWidgets import QPushButton, QLineEdit, QTableWidget, QTableWidgetItem, QLabelclass MainWindow(QWidget):def __init__(self):# 用super 继承父类的初始化super().__init__()# 设置窗口的窗体标题self.setWindowTitle('发现你走远了的xx系统')# 设置窗体的尺寸self.resize(1228, 450)# 设置窗体位置# 获取整个窗口部分的宽高和左上角坐标信息,返回值是一个QRect类型,(x,y width,height)qr = self.frameGeometry()cp = QDesktopWidget().availableGeometry().center() # 得到屏幕中间的位置信息qr.moveCenter(cp) # 让我们的窗体移动到屏幕中间# 创建窗口总布局layout = QVBoxLayout()# 1.顶部菜单布局header_layout = QHBoxLayout() # 创建顶部菜单布局# 1.1 放入按钮btn_start =QPushButton("开始")#新建一个开始按钮header_layout.addWidget(btn_start)#将开始按钮添加到顶部菜单布局btn_stop =QPushButton("停止")#新建一个开始按钮header_layout.addWidget(btn_stop)#将开始按钮添加到顶部菜单布局# 1.2 加入弹簧header_layout.addStretch()layout.addLayout(header_layout) # 将顶部菜单布局添加到总布局# 2.添加内容布局form_layout = QHBoxLayout() # 创建添加内容布局# 2.1 输入框txt_asin=QLineEdit()#新建一个输入框对象txt_asin.setText("B07YN82X3B=100")#设置默认的form数据txt_asin.setPlaceholderText("请输入商品ID和价格,例如:B0818JJQQ8=88")#设置灰色的提示信息form_layout.addWidget(txt_asin)#将输入框加入到布局中# 2.2 添加按钮btn_add = QPushButton("添加")#新建一个添加按钮form_layout.addWidget(btn_add)#将添加按钮添加到form布局layout.addLayout(form_layout) # 将添加内容布局添加到总布局# 3.表格数据展示布局table_layout = QHBoxLayout()# 3.1 创建表格table_widget=QTableWidget(0,8)#新建一个0行8列的表格# # 修改表格索引名# item=QTableWidgetItem()# item.setText("标题0")# table_widget.setHorizontalHeaderItem(0,item)# table_widget.setColumnWidth(0,150)#设置水平单元格0号位置的宽度 150## item2=QTableWidgetItem()# item2.setText("网址1")# table_widget.setHorizontalHeaderItem(1,item2)# table_widget.setColumnWidth(1,400)#设置水平单元格1号位置的宽度 400## item3=QTableWidgetItem()# item3.setText("行索引0")# table_widget.setVerticalHeaderItem(0,item3)table_header = [{"field": "asin", "text": "ASIN", 'width': 120},{"field": "title", "text": "标题", 'width': 150},{"field": "url", "text": "URL", 'width': 400},{"field": "price", "text": "底价", 'width': 100},{"field": "success", "text": "成功次数", 'width': 100},{"field": "error", "text": "503次数", 'width': 100},{"field": "status", "text": "状态", 'width': 100},{"field": "frequency", "text": "频率(N秒/次)", 'width': 100},]for idx,info in enumerate(table_header):item=QTableWidgetItem()item.setText(info['text'])table_widget.setHorizontalHeaderItem(idx,item)table_widget.setColumnWidth(idx,info['width'])table_layout.addWidget(table_widget)#把表格添加到表格布局中layout.addLayout(table_layout)# 4.底部菜单footer_layout = QHBoxLayout()label_status = QLabel("未检测", self)footer_layout.addWidget(label_status)footer_layout.addStretch()#添加弹簧,更加美观btn_reset = QPushButton("重新初始化")footer_layout.addWidget(btn_reset)btn_recheck = QPushButton("重新检测")footer_layout.addWidget(btn_recheck)btn_reset_count = QPushButton("次数清零")footer_layout.addWidget(btn_reset_count)btn_delete = QPushButton("删除检测项")footer_layout.addWidget(btn_delete)btn_alert = QPushButton("SMTP报警配置")footer_layout.addWidget(btn_alert)btn_proxy = QPushButton("代理IP")footer_layout.addWidget(btn_proxy)layout.addLayout(footer_layout)# 给窗体设置元素的排列方式self.setLayout(layout)if __name__ == '__main__':app = QApplication(sys.argv) # 实例化一个Application应用,所有的窗口均在其下运行window = MainWindow() # 实例化窗口对象window.show() # 窗口展示sys.exit(app.exec_())# app.exec_()运行主循环,并在退出时返回状态代码。# sys.exit(n)退出您的应用程序并返回n到父进程(通常是您的shell)
总结
大家喜欢的话,给个👍,点个关注!给大家分享更多计算机专业学生的求学之路!
版权声明:
发现你走远了@mzh原创作品,转载必须标注原文链接
Copyright 2023 mzh
Crated:2023-3-1
欢迎关注 『pyqt5 从0基础开始项目实战』 专栏,持续更新中
欢迎关注 『pyqt5 从0基础开始项目实战』 专栏,持续更新中
『未完待续』