PyQt 提供了丰富的布局管理器和美化操作,可以帮助开发者轻松创建复杂的用户界面。通过合理使用布局管理器、拉伸因子、对齐方式、间距设置等功能,可以设计出美观且功能强大的应用程序界面。
一、菜单栏布局与事件绑定
PyQt 的菜单栏(QMenuBar)是 GUI 应用程序中常见的顶层导航组件,通常位于窗口顶部,包含一组下拉菜单(QMenu)和菜单项(QAction)。通过
QMainWindow 类
提供的 menuBar() 方法可直接创建和管理菜单栏
1.1 菜单栏创建
一级菜单栏
# self为QMainWindow的窗口
# 创建菜单栏实例
self.MenuBar = self.menuBar()
# 添加菜单 File
self.FileMenu = self.MenuBar.addMenu("File")
# File -> Open
self.OpenFile = QAction("Open", self)
self.FileMenu.addAction(self.OpenFile)
# File -> Close
self.CloseFile = QAction("Close", self)
self.FileMenu.addAction(self.CloseFile)
多级菜单栏
self.MenuBar = self.menuBar() # MainWindw.menuBar()
# File
self.SaveMenu = self.MenuBar.addMenu("File")
# File -> Save
self.SaveFile = self.SaveMenu.addMenu("Save")
# File -> Save -> Save txt
self.SaveTxt = QAction("Save txt", self)
self.SaveFile.addAction(self.SaveTxt)
# File -> Exit
self.Exit = QAction("Exit", self)
self.SaveMenu.addAction(self.Exit)
菜单栏右侧展示按钮
self.MenuBar = self.menuBar() # MainWindw.menuBar()
# 菜单栏右侧 添加一个按钮
self.MenuBar.setCornerWidget(QtWidgets.QPushButton("Btn"), QtCore.Qt.TopRightCorner)
1.2 菜单栏属性与事件绑定
self.MenuBar = self.menuBar()
# 设置菜单栏样式(宽度)
self.MenuBar.setStyleSheet("QMenuBar {width: 100px;}")
# 获取菜单
for action in self.MenuBar.actions():
print(action.text())
self.FileMenu = self.MenuBar.addMenu("File")
self.Close = QAction("Close", self)
# 设置图标
self.Close.setIcon("icon.png")
# 添加快捷键
self.Close.setShortcut("Ctrl+S")
# 设置字体
font = QtGui.QFont('Arial', 10)
self.Close.setFont(font)
# 设置气泡
self.Close.setToolTip("Close")
# 事件绑定
self.Close.triggered.connect(self.close)
self.FileMenu.addAction(self.Close)
# 添加分隔线
self.FileMenu.addSeparator()
实例
import sys
from PyQt5 import QtWidgets, QtCore
from PyQt5.QtWidgets import QAction
# UI代码
class Ui_Form(QtWidgets.QMainWindow): # 使用菜单栏这里需要继承QMainWindow
def setupUi(self):
self.setObjectName("Form")
self.resize(300, 200)
self.MenuBar = self.menuBar()
# 菜单栏左侧
# 一级菜单栏
self.FileMenu = self.MenuBar.addMenu("File")
self.OpenFile = QAction("Open", self)
self.FileMenu.addAction(self.OpenFile)
self.FileMenu.addSeparator() # 添加分隔线
self.CloseFile = QAction("Close", self)
self.FileMenu.addAction(self.CloseFile)
# 多层菜单栏
self.SaveMenu = self.MenuBar.addMenu("Save") # 菜单栏
self.SaveFile = self.SaveMenu.addMenu("Save") # 一级菜单栏
self.SaveTxt = QAction("Save txt", self) # 二级菜单栏
self.SaveFile.addAction(self.SaveTxt)
self.Exit = QAction("Exit", self) # 一级菜单栏
self.SaveMenu.addAction(self.Exit)
# 菜单栏右侧 添加一个按钮
self.btn = QtWidgets.QPushButton("Btn")
self.MenuBar.setCornerWidget(self.btn, QtCore.Qt.TopRightCorner)
# 主体UI(略)
self.Window = QtWidgets.QWidget()
self.setCentralWidget(self.Window)
# 逻辑代码
class MainWindow(Ui_Form):
def __init__(self):
super().__init__()
self.setupUi()
# 事件绑定
self.Exit.triggered.connect(self.close)
# 运行程序
if __name__ == '__main__':
app = QtWidgets.QApplication(sys.argv)
window = MainWindow()
window.show()
sys.exit(app.exec_())
二、工具栏布局
工具栏(QToolBar)是用于快速访问常用功能的 GUI 组件,通常位于主窗口顶部或侧边。工具栏可以包含按钮、下拉菜单、分隔符等控件,支持拖拽、浮动、图标和文本显示等功能。
2.1 工具栏布局(左中右布局)
self.ToolBar = QtWidgets.QToolBar()
self.addToolBar(self.ToolBar)
# 工具栏左侧
self.File = QtWidgets.QAction("new File")
self.ToolBar.addAction(self.File)
self.Exit = QAction("Exit")
self.ToolBar.addAction(self.Exit)
# 中间隔开
specer = QtWidgets.QWidget()
specer.setSizePolicy(QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Expanding)
# 工具栏右侧
self.ToolBar.addWidget(specer)
self.btn = QtWidgets.QPushButton("按钮")
self.ToolBar.addWidget(self.btn)
2.2 工具栏属性
self.ToolBar = QtWidgets.QToolBar()
self.addToolBar(self.ToolBar)
self.File = QtWidgets.QAction()
self.ToolBar.addAction(self.File)
# 设置图标
self.File.setIcon(QIcon("icon.png"))
# 设置气泡
self.File.setToolTip("File")
# 快捷
self.File.setShortcut("Ctrl+S")
# 绑定
self.File.triggered.connect(self.close)
实例:左右两边的控件之间,中间隔开
import sys
from PyQt5 import QtCore, QtWidgets
from PyQt5.QtGui import QIcon
from PyQt5.QtWidgets import QAction
# UI代码
class Ui_Form(QtWidgets.QMainWindow):
def setupUi(self):
self.setObjectName("Form")
self.resize(300, 200)
self.ToolBar = QtWidgets.QToolBar()
# 工具栏左侧
self.addToolBar(self.ToolBar)
self.File = QtWidgets.QAction()
self.File.setIcon(QIcon("icon.png")) # 图标样式
self.File.setToolTip("File") # 气泡
self.ToolBar.addAction(self.File)
self.Exit = QAction("Exit") # 内容样式
self.ToolBar.addAction(self.Exit)
# 中间隔开
specer = QtWidgets.QWidget()
specer.setSizePolicy(QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Expanding)
self.ToolBar.addWidget(specer)
# 工具栏右侧
self.btn = QtWidgets.QPushButton("按钮") # 添加按钮
self.ToolBar.addWidget(self.btn)
# 主体UI(略)
self.Window = QtWidgets.QWidget()
self.setCentralWidget(self.Window)
# 逻辑代码
class MainWindow(Ui_Form):
def __init__(self):
super().__init__()
self.setupUi()
# 函数绑定
self.Exit.triggered.connect(self.close)
# 运行程序
if __name__ == '__main__':
app = QtWidgets.QApplication(sys.argv)
window = MainWindow()
window.show()
sys.exit(app.exec_())
三、Tab页
Tab页是用于创建多标签页界面的核心组件,它允许用户通过点击标签在不同内容面板之间切换。QTabWidget是主容器,管理所有标签页,QTabBar显示标签栏,QWidget保存每个标签页的内容面板
3.1 Tab页占整个界面
from PyQt5.QtWidgets import QApplication, QMainWindow, QTabWidget, QWidget, QLabel, QVBoxLayout
class MainWindow(QMainWindow):
def __init__(self):
super().__init__()
self.setWindowTitle("Tab 页示例")
self.setGeometry(100, 100, 600, 400)
# 创建 QTabWidget 作为中心部件
self.tab_widget = QTabWidget()
self.setCentralWidget(self.tab_widget)
# 标签页1
tab1 = QWidget()
layout1 = QVBoxLayout()
layout1.addWidget(QLabel("这是第一个标签页的内容"))
tab1.setLayout(layout1)
self.tab_widget.addTab(tab1, "标签页1")
# 标签页2
tab2 = QWidget()
layout2 = QVBoxLayout()
layout2.addWidget(QLabel("这是第二个标签页的内容"))
tab2.setLayout(layout2)
self.tab_widget.addTab(tab2, "标签页2")
if __name__ == "__main__":
app = QApplication([])
window = MainWindow()
window.show()
app.exec_()
3.2 Tab占部分界面
from PyQt5.QtWidgets import QApplication, QMainWindow, QTabWidget, QWidget, QLabel, QVBoxLayout
class MainWindow(QMainWindow):
def __init__(self):
super().__init__()
self.setWindowTitle("Tab 页示例")
self.setGeometry(100, 100, 600, 400)
# 创建主界面
self.window = QWidget()
self.setCentralWidget(self.window)
# 创建界面主布局
self.Layout = QVBoxLayout()
self.window.setLayout(self.Layout)
# 创建tab并加入到界面布局中
self.tab_widget = QTabWidget()
# Tab页1
tab1 = QWidget()
layout1 = QVBoxLayout()
layout1.addWidget(QLabel("这是第一个标签页的内容"))
tab1.setLayout(layout1)
self.tab_widget.addTab(tab1, "标签页1")
# Tab页2
tab2 = QWidget()
layout2 = QVBoxLayout()
layout2.addWidget(QLabel("这是第二个标签页的内容"))
tab2.setLayout(layout2)
self.tab_widget.addTab(tab2, "标签页2")
self.Layout.addWidget(self.tab_widget)
self.Layout.addWidget(QLabel("Tab外的界面"))
if __name__ == "__main__":
app = QApplication([])
window = MainWindow()
window.show()
app.exec_()
四、状态栏
状态栏是位于窗口底部的一个区域,用于显示应用程序的状态信息或临时消息。通常用于显示进度、帮助信息、时间等
# 状态栏
self.Status = self.statusBar()
# 显示临时消息
self.Status.showMessage("hello", 3000) # 显示三秒
# 添加永久消息
message = QtWidgets.QLabel("hello")
self.Status.addPermanentWidget(message)
实例:先展示三秒,点击按钮之后再展示三秒
import sys
from PyQt5 import QtWidgets
# UI代码
class Ui_Form(QtWidgets.QMainWindow):
def setupUi(self):
self.setObjectName("MainWindw")
self.resize(300, 200)
# 主体UI(略)
self.Window = QtWidgets.QWidget()
self.Layout = QtWidgets.QVBoxLayout()
self.btn = QtWidgets.QPushButton("OK")
self.Layout.addWidget(self.btn)
self.Window.setLayout(self.Layout)
self.setCentralWidget(self.Window)
# 状态栏
self.Status = self.statusBar()
# 显示临时消息
self.Status.showMessage("hello", 3000) # 显示三秒
# 添加永久消息
message = QtWidgets.QLabel()
self.Status.addPermanentWidget(message)
# 逻辑代码
class MainWindow(Ui_Form):
def __init__(self):
super().__init__()
self.setupUi()
# 函数绑定
self.btn.clicked.connect(self.ClickBtn)
def ClickBtn(self):
self.statusBar().showMessage("hello", 3000)
# 运行程序
if __name__ == '__main__':
app = QtWidgets.QApplication(sys.argv)
window = MainWindow()
window.show()
sys.exit(app.exec_())
五、主体布局(水平、垂直、网格、嵌套)
5.1 三大布局与嵌套布局(QHBoxLayout、QVBoxLayout、QGridLayout)
函数 | 介绍 |
---|---|
setAlignment(widget, alignment) | 控制部件对齐方式(对齐方式参考6.4 ) |
setContentMargins(left, top, right, bottom) | 设置布局边界距离 |
addWidget(widget, stretch=0, alignment=0) | 添加控件到布局,stretch 控制拉伸因子,alignment 设置对齐方式 ( 对齐方式参考6.4 ) |
setSpacing(spacing) | 设置控件之间的间距(像素) |
addStretch(stretch) | 添加可拉伸空间,用于调整控件间距 |
setStretchFactor(0, 2) | 动态调整控件比例 |
layout.setDirection(QBoxLayout.RightToLeft) | 布局的方向(从右到左) |
水平布局(QHBoxLayout)
self.HLayout = QtWidgets.QHBoxLayout()
self.Label = QtWidgets.QLabel("路径")
self.HLayout.addWidget(self.Label) # self.HLayout.addWidget(self.Label, 1)
self.Line = QtWidgets.QLineEdit()
self.HLayout.addWidget(self.Line) # self.HLayout.addWidget(self.Line, 4)
self.btn = QtWidgets.QPushButton("打开")
self.HLayout.addWidget(self.btn) # self.HLayout.addWidget(self.btn, 1)
垂直布局(QVBoxLayout)
self.VLayout = QtWidgets.QVBoxLayout()
self.btn1 = QtWidgets.QPushButton("按钮1")
self.VLayout.addWidget(self.btn1) # self.VLayout.addWidget(self.btn1, 1)
self.btn2 = QtWidgets.QPushButton("按钮2")
self.VLayout.addWidget(self.btn2) # self.VLayout.addWidget(self.btn2, 1)
self.btn3 = QtWidgets.QPushButton("按钮3")
self.VLayout.addWidget(self.btn3) # self.VLayout.addWidget(self.btn3, 1)
网格布局(QGridLayout)
self.Glayout = QtWidgets.QGridLayout()
self.Label1 = QtWidgets.QLabel("label1")
self.Glayout.addWidget(self.Label1, 0, 0, 1, 1)
self.Line1 = QtWidgets.QLineEdit()
self.Glayout.addWidget(self.Line1, 0, 1, 1, 1)
self.Btn1 = QtWidgets.QPushButton("btn1")
self.Glayout.addWidget(self.Btn1, 0, 2, 1, 1)
self.Label2 = QtWidgets.QLabel("label2")
self.Glayout.addWidget(self.Label2, 1, 0, 1, 1)
self.Line2 = QtWidgets.QLineEdit()
self.Glayout.addWidget(self.Line2, 1, 1, 1, 1)
self.Btn2 = QtWidgets.QPushButton("btn2")
self.Glayout.addWidget(self.Btn2, 1, 2, 1, 1)
嵌套布局(三种布局嵌套)
上面三中布局嵌套使用,不居中加入控件时使用
addWidget
函数,布局中加入布局时使用addLayout
函数
self.Glayout = QtWidgets.QGridLayout() # 网格布局
self.Label1 = QtWidgets.QLabel("label1")
self.Glayout.addWidget(self.Label1, 0, 0, 1, 1)
self.Line1 = QtWidgets.QLineEdit()
self.Glayout.addWidget(self.Line1, 0, 1, 1, 1)
self.Btn1 = QtWidgets.QPushButton("btn1")
self.Glayout.addWidget(self.Btn1, 0, 2, 1, 1)
self.Hlayout = QtWidgets.QHBoxLayout() # 水平布局
self.Label2 = QtWidgets.QLabel("label2")
self.Hlayout.addWidget(self.Label2)
self.Line2 = QtWidgets.QLineEdit()
self.Hlayout.addWidget(self.Line2)
self.Btn2 = QtWidgets.QPushButton("btn2")
self.Hlayout.addWidget(self.Btn2)
self.Glayout.addLayout(self.Hlayout, 1, 0, 1, 3) # 网格布局中加入水平布局
5.3 分隔条布局(QSplitter)
QSplitter 是 Qt 框架中的一个布局控件,用于实现可调整大小的分割窗口。通过拖动分割条(splitter handle),用户可以动态调整子控件的大小比例,适用于需要灵活划分界面区域的场景。
常用方法 | 含义 |
---|---|
addWidget(QWidget *widget) | 添加控件 |
setStretchFactor(0, 1) | 设置第一个子部件的拉伸因子为1 |
splitter.splitterMoved.connect | 事件绑定 |
setMinimumSize(100, 100) | 设置最小尺寸 |
setMaximumsize(600, 600) | 设置最大尺寸 |
insertWidget(int index, QWidget *widget) | 在指定位置插入控件 |
setOrientation(Qt::Orientation orientation) | 设置布局方向(水平或垂直) |
setSizes(const QList &list) | 设置子控件的大小 |
sizes() | 获取子控件的当前大小 |
setHandleWidth(10) | 分隔条宽度 |
setSizes([100, 200]) | 设置分隔两侧的区域大小(一边为100,一边为200) |
self.Layout = QtWidgets.QVBoxLayout()
self.splitter= QtWidgets.QSplitter()
self.tree1 = QtWidgets.QTreeWidget()
self.tree2 = QtWidgets.QTreeWidget()
# tree1 tree2之间分隔线可以拖动
self.splitter.addWidget(self.tree1) # 加入tree1
self.splitter.addWidget(self.tree2) # 加入tree2
self.Layout.addWidget(self.splitter)
六、界面布局
6.1 大小策略(拉升时控件动态行为)
setSizePolicy(horizontalPolicy, verticalPolicy)
设置控件的水平方向和垂直方向的大小策略。这些策略决定了控件在布局中的行为,例如:控件是否可以扩展以填充可用空间; 控件是否可以缩小到比其推荐大小更小;控件的大小是否固定。通过设置大小策略,可以
控制控件在布局中的动态行为,从而实现更灵活的界面布局
horizontalPolicy:控件在水平方向上的大小策略,类型为 QSizePolicy.Policy。
verticalPolicy:控件在垂直方向上的大小策略,类型为 QSizePolicy.Policy。
常见大小策略如下
策略 | 含义 |
---|---|
QSizePolicy.Fixed | 大小固定 |
QSizePolicy.Minimum | 不能小于某值 |
QSizePolicy.Maximum | 不能大于某值 |
QSizePolicy.Preferred | 首选大小的值,可以根据布局的需要缩小或放大(默认的策略) |
QSizePolicy.Expanding | 可以缩小到比设置的值更小,也可以扩展到填充可用空间 |
QSizePolicy.MinimumExpanding | 不能小于设置的值,但可以扩展到填充可用空间 |
QSizePolicy.Ignored | 忽略设置的值,控件的大小完全由布局决定 |
实例
# 设置按钮1的大小策略为 Fixed
button1.setSizePolicy(QSizePolicy.Fixed, QSizePolicy.Fixed)
# 设置按钮2的大小策略为 Expanding
button2.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding)
6.2 空白间距
addSpacing(size)
用于在布局中
添加固定大小的空白间距
。它通常用于在控件之间添加固定的间隔,以调整布局的外观。
size:为一个整数,表示要添加的空白区域的大小(以像素为单位)。
实例
layout.addWidget(button1)
layout.addSpacing(40) # 在按钮1和按钮2之间添加40像素的间距
layout.addWidget(button2)
layout.addSpacing(20) # 在按钮2和按钮3之间添加20像素的间距
layout.addWidget(button3)
addSpacerItem(spacerItem)
向布局中
添加一个自定义的空白区域,这个空白区域可以动态调整大小,也可以固定大小
。它通常用于在布局中填充额外的空间,或者控制控件之间的对齐方式,比addSpacing更灵活。
spacerItem:是一个 QSpacerItem 对象,表示要添加到布局中的空白区域
QSpacerItem(width, height, hPolicy, vPolicy)**:(用到的大小策略参考上方)
width:空白区域的宽度。
height:空白区域的高度。
hPolicy:水平方向的大小策略(QSizePolicy.Policy)。
vPolicy:垂直方向的大小策略(QSizePolicy.Policy)。
实例:添加一个动态调整大小的空白区域
layout = QVBoxLayout()
button1 = QPushButton('Button 1')
layout.addWidget(button1)
# 创建一个动态调整大小的空白区域,并添加到布局中
layout.addSpacerItem(QSpacerItem(20, 40, QSizePolicy.Minimum, QSizePolicy.Expanding))
6.3 拉伸因子(控件拉升空间分配)
setStretch(index, stretch)
设置控件在布局中的拉伸因子(Stretch Factor)。
拉伸因子决定了当布局中有额外空间时,控件如何分配这些空间
。拉伸因子越大,控件占用的额外空间越多,拉伸因子为 0 表示控件不会占用额外空间。通过设置拉伸因子,可以灵活地控制控件在布局中的大小和位置。
index:控件在布局中的索引(从 0 开始)。
stretch:控件的拉伸因子(整数)
layout.addWidget(button1)
layout.addWidget(button2)
layout.addWidget(button3)
# 设置按钮的拉伸因子
layout.setStretch(0, 1) # Button 1 的拉伸因子为 1
layout.setStretch(1, 2) # Button 2 的拉伸因子为 2
layout.setStretch(2, 1) # Button 3 的拉伸因子为 1
6.4 对齐方式(控件、布局)
setAlignment(alignment)
设置控件或布局对齐方式的方法。它可以应用于布局类或控件本身,用于
控制控件在布局中的对齐方式
。
alignment:对齐方式,类型为 Qt.AlignmentFlag 或其组合,组合对其需要使用 | 符号
对齐方式 | 描述 |
---|---|
Qt.AlignLeft | 左对齐 |
Qt.AlignRight | 右对齐 |
Qt.AlignHCenter | 水平居中对齐 |
Qt.AlignJustify | 两端对齐(仅适用于文本) |
Qt.AlignTop | 顶部对齐 |
Qt.AlignBottom | 底部对齐 |
Qt.AlignVCenter | 垂直居中对齐 |
# 文本对齐方式为居中对齐
label.setAlignment(Qt.AlignHCenter | Qt.AlignVCenter)
# 设置布局中所有控件的默认对齐方式为右对齐
layout.setAlignment(Qt.AlignRight)
七、附录
7.1 PyQt 界面编程:QDialog、QWidget、QMainWindow 的面向过程与面向对象编程
参考链接:PyQt 界面编程:QDialog、QWidget、QMainWindow 的面向过程与面向对象编程
7.2 PyQt常用控件的使用:QFileDialog、QMessageBox、QTreeWidget、QRadioButton等
参考链接:PyQt常用控件的使用:QFileDialog、QMessageBox、QTreeWidget、QRadioButton等