PyQt 界面设置与布局:菜单栏、工具栏、主体、提示栏布局

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等

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值