21. 窗口控件

一、窗口控件

  之前,我们创建具体的控件实例(例如标签控件、按钮控件等)时都选择了一个父窗体,将控件放到这个窗体上,即使在创建实例时没有选择父窗体,也可以用控件的 setParent(wiget:QWidget) 方法将控件放到父窗体上。如果一个控件没有放到任何窗体上,则这个控件可以单独成为窗口,并且可以作为父窗口来使用,可在其上面添加其他控件,这种控件可以称为程序的独立窗口。

  QWidget 控件可以当作普通的容器控件使用,也可以当作独立的窗口来使用。当一个控件有父窗口时,不显示该控件的标题栏;当控件没有父窗口时,会显示标题栏。

  QWidget 是可视化控件的基类,而 QWidget 是从 QObjectQPaintDevice 类继承而来的,QObject 主要 定义信号和槽的功能QPaintDevice 主要 定义绘图功能

  我们可以在终端中使用 pip 安装 PySide6 模块。默认是从国外的主站上下载,因此,我们可能会遇到网络不好的情况导致下载失败。我们可以在 pip 指令后通过 -i 指定国内镜像源下载

pip install pyside6 -i https://mirrors.aliyun.com/pypi/simple

  国内常用的 pip 下载源列表:

  用 QWidget 创建实例对象的方法如下:

QWidget(parent:QWidget=None, kind:Qt.WindowType=Qt.WindowType.Widget)

  其中 parent父窗口控件,如果没有给 QWidget 传递父窗口控件,QWidget 将会成为独立窗口。QWidget 中的参数 kindQt.WindowType 类型的枚举值,用于 确定窗口的类型和外观,如果同时选择多个值,可以用 | 符号将多个可选值连接起来。窗口类型和外观与系统有关,取决于系统是否支持窗口类型和外观。

  参数 kind 是窗口类型的 Qt.WindowType 类型的枚举值,可以取值如下:

Qt.WindowType.Widget                                                            # 默认值,如果QWidget有父容器或者窗口,它是一个控件,如果没有是独立窗口
Qt.WindowType.Window                                                            # 不管QWidget是否有父容器或者窗口,它都是窗口
Qt.WindowType.Dialog                                                            # 对话框窗口
Qt.WindowType.Sheet                                                             # 在Mac系统中,QWidget是一个表单
Qt.WindowType.Drawer                                                            # 在Mac系统中,QWidget是一个抽屉
Qt.WindowType.Popup                                                             # QWidget是一个弹出式顶层窗口
Qt.WindowType.Tool                                                              # QWidget是一个工具窗
Qt.WindowType.ToolTip                                                           # QWidget是一个提示窗,没有标题栏和边框
Qt.WindowType.SplashScreen                                                      # QWidget是一个欢迎窗
Qt.WindowType.Desktop                                                           # QWidget是一个桌面
Qt.WindowType.SubWindow                                                         # QWidget是一个子窗口
Qt.WindowType.ForeignWindow                                                     # QWidget是由其它程序创建的句柄窗口
Qt.WindowType.CoverWindow                                                       # QWidget是一个封面窗口,单行程序最小化是显示该窗口

  影响窗口外观的 Qt.WindowType 枚举值取值如下:

Qt.WindowType.MSWindowsFixedSizeDialogHint                                      # 对于不可调整尺寸的对话框添加窄的边框
Qt.WindowType.MSWindowsOwnDC                                                    # 为Window系统的窗口添加下上文菜单
Qt.WindowType.BypassWindowManagerHint                                           # 窗口不受窗口管理协议的约束,与具体的操作系统有关
Qt.WindowType.X11BypassWindowManagerHint                                        # 无边框窗口,不受任何任务管理器的管理,如果不是用activareWindow()方法激活,不接受键盘输入
Qt.WindowType.FramelessWindowHint                                               # 无边框和标题栏,无法移动或改变窗口的尺寸
Qt.WindowType.NoDropShadowWindowHint                                            # 不支持拖放操作的窗口
Qt.WindowType.CustomizeWindowHint                                               # 自定义窗口标题栏,不显示窗口的默认提示信息,以下6个可选值可配合该值一起使用
Qt.WindowType.WindowTitleHint                                                   # 有标题栏的窗口
Qt.WindowType.WindowSystemMenuHint                                              # 有系统菜单的窗口
Qt.WindowType.WindowMinimizeButtonHint                                          # 有最小化按钮的窗口  
Qt.WindowType.WindowMaximizeButtonHint                                          # 有最大化按钮的窗口
Qt.WindowType.WindowMinMaxButtonsHint                                           # 有最小化和最大化按钮的窗口
Qt.WindowType.WindowCloseButtonHint                                             # 有关闭按钮的窗口
Qt.WindowType.WindowContextHelpButtonHint                                       # 有帮助按钮的窗口
Qt.WindowType.MacWindowToolBarButtonHint                                        # 在Mac系统中,添加工具栏按钮
Qt.WindowType.WindowFullscreenButtonHint                                        # 有全屏按钮的窗口
Qt.WindowType.WindowShadeButtonHint                                             # 在最小化按钮处添加背景按钮
Qt.WindowType.WindowStaysOnTopHint                                              # 始终在最前面的窗口
Qt.WindowType.WindowStaysOnBottomHint                                           # 始终在最后面的窗口
Qt.WindowType.WindowTransparentForInput                                         # 只用于输出,不能用于输入的窗口
Qt.WindowType.WindowDoesNotAcceptFocus                                          # 不接受输入焦点的窗口
Qt.WindowType.MaximizeUsingFullscreenGeometryHint                               # 窗口最大化时,最大化地占据屏幕

  由于 QWidget 可以成为顶层窗口、独立窗口和容器控件,因此 QWidget 的方法根据 QWidget 的功能不同也会有所不同。顶层窗口一定是独立窗口,而独立窗口不一定是顶层窗口,独立窗口也可以有父窗口。QWidget 的一些属性只能用于窗口,一些只能用于控件,一些既可以用于窗口也可以用于控件。

# 实例方法
setWindowIcon(icon:QIcon) -> None                                               # 设置窗口的图标
windowIcon() -> QIcon                                                           # 获取窗口的图标

setWindowIconText(text:str) -> None                                             # 设置窗口图标的文字
windowIconText() -> str                                                         # 获取窗口图标的文字

windowType() -> Qt.WindowType                                                   # 获取窗口类型
windowTitle() -> str                                                            # 获取窗口的标题

isWindowModified() -> bool                                                      # 获取窗口是否被修改

setWindowModality(windowModality:Qt.WindowModality) -> None                     # 设置窗口的模式特征
windowModality() -> Qt.WindowModality                                           # 获取窗口的模式特征
isModal() -> bool                                                               # 获取窗口是否有模式特征

setWindowOpacity(level:float) -> None                                           # 设置窗口的不透明度,参数从0到1
windowOpacity() -> float                                                        # 获取窗口的不透明度

setWindowState(state:Qt.WindowState) -> None                                    # 设置窗口状态
windowState() -> Qt.WindowState                                                 # 获取窗口状态

activateWindow() -> None                                                        # 激活窗口
isActiveWindow() -> bool                                                        # 获取窗口是否处于活动状态

setMinimumWidth(width:int) -> None                                              # 设置窗口或控件的最小宽度
setMinimumHeight(height:int) -> None                                            # 设置窗口或控件的最小高度
setMinimumSize(size:QSize) -> None                                              # 设置窗口或控件的最小尺寸
setMinimumSize(width:int, height:int) -> None                                   # 设置窗口或控件的最小尺寸
isMinimized() -> bool                                                           # 获取是否处于最小化状态

setMaximumWidth(width:int) -> None                                              # 设置窗口或控件的最大宽度
setMaximumHeight(height:int) -> None                                            # 设置窗口或控件的最大高度
setMaximumSize(size:QSize) -> None                                              # 设置窗口或控件的最大尺寸
setMaximumSize(width:int, height:int) -> None                                   # 设置窗口或控件的最大尺寸
isMaximized() -> bool                                                           # 获取是否处于最大化状态

setFixedWidth(width:int) -> None                                                # 设置窗口或控件的固定宽度
setFixedHeight(height:int) -> None                                              # 设置窗口或控件的固定高度
setFixedSize(size:QSize) -> None                                                # 设置窗口或控件的固定尺寸
setFixedSize(width:int, height:int) -> None                                     # 设置窗口或控件的固定尺寸

isFullScreen() -> bool                                                          # 获取是否处于全屏状态
isHidden() -> bool                                                              # 获取是否处于隐藏状态
isEnabled() -> bool                                                             # 获取激活状态

setVisible(visible:bool) -> None                                                # 设置窗口是否可见
isVisible() -> bool                                                             # 获取是否可见

isWindow() -> bool                                                              # 获取是否是独立窗口
window() -> QWidget                                                             # 返回控件所在的独立窗口

setAutoFillBackground(enabled:bool) -> None                                     # 设置是否自动填充背景色
autoFillBackground() -> bool                                                    # 获取是否自动填充背景色

setFont(font:QFont) -> None                                                     # 设置字体
font() -> QFont                                                                 # 获取字体

setPalette(palette:QPalette) -> None                                            # 设置调色板
palette() -> QPalette                                                           # 获取调色板

setCursor(cursor:QCursor) -> None                                               # 设置光标
cursor() -> QCursor                                                             # 获取光标
unsetCursor() -> None                                                           # 重置光标,使用父窗口的光标

setContextMenuPolicy(policy:Qt.ContextMenuPolicy) -> None                       # 设置右键快捷菜单的弹出策略
contextMenuPolicy() -> Qt.ContextMenuPolicy                                     # 获取右键快捷菜单的弹出策略

addAction(action:Qt.QAction) -> None                                            # 添加一个动作,以便形成右键快捷菜单
addActions(actions:Sequence[Qt.QAction]) -> None                                # 添加多个动作,以便形成右键快捷菜单

insertAction(before:Qt.QAction, action:Qt.QAction) -> None                      # 在指定动作之前添加一个动作
insertActions(before:Qt.QAction, actions:Sequence[Qt.QAction]) -> None          # 在指定动作之前添加多个动作

actions() -> List[Qt.QAction]                                                   # 获取所有动作

scroll(dx:int, dy:int) -> None                                                  # 窗口中的控件向左、向下移动指定的像素,参数可为负
scroll(dx:int, dy:int, r:QRect) -> None                                         # 窗口中的控件向左、向下移动指定的像素,参数可为负

setUpdatesEnabled(enable:bool) -> None                                          # 设置是否可以对窗口进行刷新

update(r:Uinon[QRect, QRegion]) -> None                                         # 刷新窗口的指定区域
update(x:int, y:int, width:int, height:int) -> None                             # 刷新窗口的指定区域

repaint(rect:QRect) -> None                                                     # 重绘指定区域
repaint(x:int, y:int, width:int, height:int) -> None                            # 重绘指定区域

resize(size:QSize) -> None                                                      # 重新设置窗口工作区的尺寸
resize(width:int, height:int) -> None                                           # 重新设置窗口工作区的尺寸
size() -> QSize                                                                 # 获取窗口工作区的尺寸

move(point:QPoint) -> None                                                      # 移动左上角到指定位置
move(x:int, y:int) -> None                                                      # 移动左上角到指定位置
pos() -> QPoint                                                                 # 获取窗口左上角位置
x() -> int                                                                      # 获取窗口左上角X坐标
y() -> int                                                                      # 获取窗口左上角Y坐标

setGeometry(rect:QRect) -> None                                                 # 设置窗口的尺寸和位置
setGeometry(x:int, y:int, width:int, height:int) -> None                        # 设置窗口的尺寸和位置
geometry() -> QRect                                                             # 获取窗口的尺寸和位置
rect() -> QRect                                                                 # 获取窗口的尺寸和位置
childrenRect() -> QRect                                                         # 获取子控件的尺寸和位置

frameSize() -> QSize                                                            # 获取窗口的尺寸
frameGeometry() -> QRect                                                        # 获取窗口的尺寸和位置

setBaseSize(size:QSize) -> None                                                 # 设置控件的合适尺寸
setBaseSize(width:int, height:int) -> None                                      # 设置控件的合适尺寸
baseSize() -> QSize                                                             # 获取控件的合适尺寸

setContentsMargins(margins:QMargins) -> None                                    # 设置左、上、右、下的页边距
setContentsMargins(left:int, top:int, right:int, bottom:int) -> None            # 设置左、上、右、下的页边距

setWhatsThis(test:str) -> None                                                  # 设置按Shift+F1查看的提示信息
setToolTip(text:str) -> None                                                    # 设置控件的提示信息
setToolTipDuration(msec:int) -> None                                            # 设置控件的提示信息持续时间(毫秒) 

childAt(point:QPoint) -> QWidget                                                # 获取指定位置处的控件
childAt(point:QPointF) -> QWidget                                               # 获取指定位置处的控件
childAt(x:int, y:int) -> QWidget                                                # 获取指定位置处的控件

setLayout(layout:QLayout) -> None                                               # 设置窗口或控件内的布局
layout() -> QLayout                                                             # 获取窗口或控件内的布局
setLayoutDirection(direction:Qt.LayoutDirection) -> None                        # 设置布局的排列方向

setParent(parent:QWidget) -> None                                               # 设置控件的父控件
setParent(parent:QWidget, f:Qt.WindowType) -> None                              # 设置控件的父控件
parentWidget() -> QWidget                                                       # 获取控件的父控件

setSizeIncrement(size:QSize) -> None                                            # 设置窗口变化时的增量值
setSizeIncrement(width:int, height:int) -> None                                 # 设置窗口变化时的增量值
sizeIncrement() -> QSize                                                        # 获取窗口变化时的增量值

setMask(bitmap:QBitmap) -> None                                                 # 设置遮掩,白色部分不显示,黑色部分显示
setStyle(style:QStyle) -> None                                                  # 设置窗口的风格
setAttribute(attribute:Qt.WidgetAttribute, on:bool=true) -> None                # 设置窗口的属性

setAcceptDrops(on:bool) -> None                                                 # 设置是否接受鼠标的拖放
setMouseTracking(enable:bool) -> None                                           # 设置是否追踪鼠标的移动事件
hasMouseTracking() -> bool                                                      # 获取是否追踪鼠标的移动事件
underMouse() -> bool                                                            # 获取鼠标是否处于光标之下

setWindowFilePath(filePath:str) -> None                                         # 在窗口上记录一个路径

mapFrom(parent:QWidget, pos:QPoint) -> QPoint                                   # 将父容器的点映射成控件坐标系下的点
mapFrom(parent:QWidget, pos:QPointF) -> QPointF                                 # 将父容器的点映射成控件坐标系下的点
mapTo(parent:QWidget, pos:QPoint) -> QPoint                                     # 将控件的点映射成父容器坐标系下的点
mapTo(parent:QWidget, pos:QPointF) -> QPointF                                   # 将控件的点映射成父容器坐标系下的点

mapFromGlobal(pos:Qpoint) -> QPoint                                             # 将屏幕坐标系中的点映射成控件的点
mapFromGlobal(pos:QpointF) -> QPointF                                           # 将屏幕坐标系中的点映射成控件的点
mapToGlobal(pos:QPoint) -> QPoint                                               # 将控件的点映射成屏幕坐标系下的点
mapToGlobal(pos:QPointF) -> QPointF                                             # 将控件的点映射成屏幕坐标系下的点

mapFromParent(pos:QPoint) -> QPoint                                             # 将父容器坐标系下中的点映射成控件的点
mapFromParent(pos:QPointF) -> QPointF                                           # 将父容器坐标系下中的点映射成控件的点
mapToParent(pos:QPoint) -> QPoint                                               # 将控件的点映射成父容器坐标系下的点
mapToParent(pos:QPointF) -> QPointF                                             # 将控件的点映射成父容器坐标系下的点

grab(rectangle:QRect=QRect(QPoint(0, 0), QSize(-1, -1))) -> QPixmap             # 截取控件指定范围的图像,默认为整个控件

grabKeyboard() -> None                                                          # 获取所有的键盘输入事件,其它控件不再接受键盘输入事件
releaseKeyboard() -> None                                                       # 不再获取键盘输入事件

grabMouse() -> None                                                             # 获取所有的鼠标输入事件,其它控件不再接受鼠标输入事件
grabMouse(cursor:QCursor) -> None                                               # 获取所有的鼠标输入事件并改变光标形状
releaseMouse() -> None                                                          # 不再获取鼠标输入事件

# 静态方法
static find(id:int) -> QWidget                                                  # 根据控件的识别ID号或句柄ID号获取控件
static keyboardGrabber() -> QWidget                                             # 返回键盘获取的控件
static mouseGrabber() -> QWidget                                                # 获取鼠标获取的控件
static setTabOrder(first:QWidget, second:QWidget) -> None                       # 设置窗口上的控件的Tab顺序

# 槽方法
show() -> None                                                                  # 显示窗口
close() -> bool                                                                 # 关闭窗口,如果成功返回True

hide() -> None                                                                  # 隐藏窗口
setHidden(hidden:bool) -> None                                                  # 设置隐藏状态

raise_() -> None                                                                # 提升控件,放到栈控件的顶部
lower() -> None                                                                 # 降低控件,放到栈控件的底部

setWindowTitle(title:str) -> None                                               # 设置窗口标题
setWindowModified(modified:bool) -> None                                        # 设置文档是否修改过
setFocus() -> None                                                              # 设置窗口获得焦点
setStyleSheet(styleSheet:str) -> None                                           # 设置窗口或控件的样式表

showFullScreen() -> None                                                        # 全屏显示
showMaximized() -> None                                                         # 最大化显示
showMinimized() -> None                                                         # 最小化显示
showNormal() -> None                                                            # 最大化或者最小化显示后恢复成正常显示

update() -> None                                                                # 更新窗口
repaint() -> None                                                               # 调用paintEvent事件重新绘制窗口

  QWidget 窗口的常用信号如下:

windowIconChanged(icon:QIcon)                                                   # 窗口图标改变时发送信号
windowIconTextChanged(iconText:str)                                             # 窗口图标文本改变时发送信号
windowTitleChanged(title:str)                                                   # 窗口标题改变时发送信号
customContextMenuRequested(pos:QPoint)                                          # 右键弹出自定义菜单时发送信号

  用 show() 方法可以 显示窗口,用 hide() 方法可以 隐藏窗口,也可以用 setVisible(visible:bool)方法和 setHidden(hidden:bool) 方法 设置窗口的可见性,用 isVisible()isHidden() 方法 判断窗口是否可见,用 close() 方法可以 关闭窗口close() 方法的返回值 bool 表示关闭事件是否被接受,也就是窗口是否真的被关闭了。

  当窗口被关闭时,首先向这个窗口发送一个关闭事件 closeEvent(event:QCloseEvent),如果事件被接受,则窗口被隐藏;如果事件被拒绝,则什么也不做。如果创建窗口时用 setAttribute(Qt.WA_QuitOnClose, on=True)方法设置了 Qt.WA_QuitOnClose 属性,则窗口对象会被析构(删除),大多数类型的窗口都默认设置了这个属性。

  如果显示多个窗口,则窗口之间是有先后顺序的,用 raise_() 方法可 把窗口放到前部,用 lower() 方法可以 把窗口放到底部

  我们可以用 setWindowState(state:Qt.WindowStates)方法 设置窗口的状态,其中参数 stateQt.WindowStates 类型的枚举值,可以取值如下:

Qt.WindowState.WindowNoState                                                    # 无标识,正常状态
Qt.WindowState.WindowMinimized                                                  # 最小化状态
Qt.WindowState.WindowMaximized                                                  # 最大化状态
Qt.WindowState.WindowFullScreen                                                 # 全屏状态
Qt.WindowState.WindowActive                                                     # 激活状态

窗口几何参数

  窗口尺寸的设置是在屏幕坐标系下进行的,屏幕坐标系的原点在左上角,向右表示 x 方向,向下表示 y 方向。我们可以用 x()y()pos() 方法可以 获得窗口左上角的坐标,用 frameGeometry() 方法可以 获得窗口框架的几何参数,用 frameSize() 方法可以 获得框架的宽度和高度,用 geometry() 方法可以 获得工作区的几何参数,包括左上角的位置和宽度、高度,用 rect()size()width()height() 方法可以 获得工作区的宽度、高度

  我们还可以用 move(int:x, int:y) 方法可以 将窗口左上角移动到坐标 (x,y),用 move(point:QPoint) 方法可以 将窗口左上角移动到 QPoint,用 resize(width:int, height:int) 方法可以 设置工作区的宽度和高度,用 resize(size:QSize) 方法可以 将工作区宽度和高度设置成 size,用 setGeometry(x:int,y:int,w:int,h:int) 方法可以将工作区的 左上角移动到 (x,y)宽度改为 width高度改为 height

  在主窗口中通常需要弹出一些需要进行设置或确认信息的对话框,在对话框没有关闭之前,通常不能对其他窗口进行操作,这就是窗口的模式。用 setWindowModality(modality:Qt.WindowModality) 方法 设置窗口的模式特性,其中参数 modalityQt.WindowModality 类型的枚举值,可以取值如下:

Qt.WindowModality.NonModal                                                      # 非模式,可以和程序的其他窗口进行交互操作
Qt.WindowModality.WindowModal                                                   # 窗口模式,在未关闭当前窗口时,将阻止与该窗口的父辈窗口的交互操作
Qt.WindowModality.ApplicationModal                                              # 应用程序模式,在未关闭当前窗口时,将阻止窗口与任何其他窗口的交互操作

  用 setLayout(layout:QLayout) 方法可以 设置窗口的布局,用 layout() 方法可以 获取窗口的布局,用 setLayoutDirection(direction:Qt.LayoutDirection) 方法可以 设置布局的方向,其中参数 directionQt.LayoutDirection类型的枚举值,可以取值如下:

Qt.LayoutDirection.LeftToRight
Qt.LayoutDirection.RightToLeft
Qt.LayoutDirection.LayoutDirectionAuto

  用 setAttribute(attribute:Qt.WidgetAttribute, on:bool=True) 方法可以 设置窗口的属性,用 testAttribute(attribute:Qt.WidgetAttribute) 方法可以 测试是否设置了某个属性,其中参数 attributeQt.WidgetAttribute 类型的枚举值,可以取值如下:

Qt.WidgetAttribute.WA_DeleteOnClose                                             # 调用close()方法时删除窗口而不是隐藏窗口
Qt.WidgetAttribute.WA_QuitOnClose                                               # 最后一个窗口如果有Qt.WidgetAttribute.WA_DeleteOnClose属性,则执行close()方法发时退出程序 
Qt.WidgetAttribute.WA_AcceptDrops                                               # 窗口接受拖拽的数据
Qt.WidgetAttribute.WA_AlwaysShowToolTips                                        # 窗口失效时也能显示提示信息
Qt.WidgetAttribute.WA_Disabled                                                  # 窗口处于失效状态,不接收键盘和鼠标的输入
Qt.WidgetAttribute.WA_DontShowOnScreen                                          # 窗口隐藏
Qt.WidgetAttribute.WA_ForceDisabled                                             # 即使父窗口处于激活状态,窗口也强制失效
Qt.WidgetAttribute.WA_TransparentForMouseEvents                                 # 窗口和其子窗口忽略鼠标事件
Qt.WidgetAttribute.WA_RightToLeft                                               # 布局方向从右向左
Qt.WidgetAttribute.WA_ShowWithoutActivating                                     # 当不激活窗口时,显示窗口

  在窗口或控件上右击鼠标时,将弹出右键快捷菜单(上下文菜单),用 setContextMenuPolicy(policy:Qt.ContextMenuPolicy) 方法 设置弹出快捷菜单的策略和处理方式,其中 policyQt.ContextMenuPolicy 类型的枚举值,可取值如下所示:

Qt.ContextMenuPolicy.NoContextMenu                                              # 控件没有自己特有的快捷菜单,使用控件父窗口或父容器的快捷菜单
Qt.ContextMenuPolicy.DefaultContextMenu                                         # 鼠标右键事件交给控件的contextMenuEvent()函数处理
Qt.ContextMenuPolicy.ActionsContextMenu                                         # 右键快捷菜单是控件或窗口的actions()方法获取的动作
Qt.ContextMenuPolicy.CustomContextMenu                                          # 用户自定义快捷菜单,右击鼠标时,发射sustomContextMenuRequested(point:QPoint)信号
Qt.ContextMenuPolicy.PreventContextMenu                                         # 鼠标右键事件交给控件的mousePressEvent()和mouseReleaseEvent()函数进行处理

  我们新建一个 ui.py 文件,用来存放 UI 相关的代码。

from PySide6.QtWidgets import QWidget
from PySide6.QtGui import QIcon

class MyUi:
    def setupUi(self, window:QWidget):
        window.resize(800, 600)                                                 # 1.设置窗口对象大小

        window.setObjectName("Window")                                          # 2.设置窗口的唯一标识
        window.setWindowTitle("基于PySide6的桌面应用程序")                         # 3.设置窗口的标题

        icon = QIcon("assets/images/1.ico")
        window.setWindowIcon(icon)                                              # 4.设置窗口的图标

        window.setStyleSheet("background-color:pink")                           # 5.设置背景颜色
        window.setWindowOpacity(0.8)                                            # 6.设置窗口不透明度

  我们新建一个 widget.py 文件,用来存放业务逻辑相关的代码。

import sys

from PySide6.QtWidgets import QApplication, QWidget

from ui import MyUi

class MyWidget(QWidget):
    def __init__(self):
        super().__init__()                                                      # 1.调用父类Qwidget类的__init__()方法
      
        self.__ui = MyUi()
        self.__ui.setupUi(self)                                                 # 2.初始化页面

if __name__ == "__main__":
    app = QApplication(sys.argv)                                                # 1.创建一个QApplication类的实例
    window = MyWidget()                                                         # 2.创建一个窗口
    window.show()                                                               # 3.显示窗口
    sys.exit(app.exec())                                                        # 4.进入程序的主循环并通过exit()函数确保主循环安全结束

二、菜单和动作

  一般菜单栏由多个菜单构成,菜单下面又有动作、子菜单和分隔条,子菜单下面又有动作,还可以有子菜单,动作上有图标和快捷键。

  建立一个菜单分为 3 步。

  1. 需要建立放置菜单的容器,即菜单栏;
  2. 在菜单栏上添加菜单,或者在菜单上添加子菜单;
  3. 在菜单栏、菜单或子菜单下面添加动作,并为动作编写槽函数。

建立菜单的步骤

菜单一般不执行命令,其作用类似于标签,只有动作才可以发送信号,执行关联的槽函数。

2.1、菜单栏

  QMenuBar 类是所有窗口的 菜单栏,用户需要再次基础上添加不同的 QMenuQAction 类。我们可以通过如下方式创建菜单栏。

QMenuBar(parent:QWidget=None)

  QMenuBar 类的常用方法如下:

addMenu(menu:QMenu) -> QAction                                                  # 添加已经存在的菜单
addMenu(text:str) -> QMenu                                                      # 用字符串添加菜单,并返回菜单
addMenu(icon:QIcon, text:str) -> QMenu                                          # 用图标和字符串添加菜单,并返回菜单

insertMenu(before:QAction, menu:QMenu) -> QAction                               # 在指定的动作之前插入菜单

addAction(action:QAction) -> None                                               # 添加已经存在的动作
addAction(text:str) -> QAction                                                  # 用字符串添加动作,并返回动作

addSeparator() -> QAction                                                       # 添加分隔符

insertSeparator(before:QAction) -> QAction                                      # 在指定的动作之前插入分隔符

clear() -> None                                                                 # 清空菜单

setCornerWidget(widget:QWidget, corner:Qt.Corner=Qt.Corner.TopRightCorner) -> None  # 在菜单栏的角落位置添加控件
cornerWidget(corner:Qt.Corner=Qt.Corner.TopRightCorner) -> QWidget              # 获取角落位置的控件

setActiveAction(action:QAction) -> None                                         # 设置高亮显示的动作
actionAt(point:QPoint) -> QAction                                               # 获取指定位置的动作
actionGeometry(action:QAction) -> QRect                                         # 获取动作的矩形

  QMenuBar 类的常用信号如下:

hovered(action:QAction)                                                         # 当光标划过控件时发射信号
triggered(action:QAction)                                                       # 当单击菜单栏上的菜单或动作时发射信号

  菜单栏上可以添加菜单、动作和分隔条,用 addMenu(menu:QMenu) 方法和 addAction(action:QAction) 方法可以 添加已经提前定义好的菜单和动作。用 addMenu(text:str) 方法和 addMenu(icon:QIcon, text:str) 方法可以 创建并添加菜单,并返回新建立的菜单。用 addAction(text:str) 方法可以 用字符串创建并添加动作,并返回动作

  用 setCornerWidget(widget:QWidget, corner:Qt.Corner=Qt.Corner.TopRightCorner) 方法可以 在菜单栏的角落位置添加控件,参数 cornerQt.Corner 类型的枚举值,可以取值如下:

Qt.Corner.TopLeftCorner
Qt.Corner.TopRightCorner
Qt.Corner.BottomLeftCorner
Qt.Corner.BottomRightCorner

  修改 ui.py 文件的内容。

from PySide6.QtWidgets import QWidget
from PySide6.QtWidgets import QMenuBar, QLabel
from PySide6.QtWidgets import QVBoxLayout

class MyUi:
    def setupUi(self, window:QWidget):
        window.resize(800, 600)                                                 # 1.设置窗口对象大小

        layout = QVBoxLayout(window)                                            # 2.创建一个垂直布局

        self.menuBar = QMenuBar(window)                                         # 3.创建菜单栏
        self.menuBar.setFixedHeight(30)                                         # 4.设置菜单栏宽度
        layout.addWidget(self.menuBar)                                          # 5.添加菜单栏到布局中

        self.file_menu = self.menuBar.addMenu("文件(&F)")                        # 6.向菜单栏中添加菜单

        self.file_menu.addAction("新建文件")                                     # 7.向菜单中添加动作
        self.file_menu.addAction("新建文件夹")

        self.file_menu.addSeparator()                                           # 8.添加分隔符

        self.file_menu.addAction("打开文件")
        self.file_menu.addAction("打开文件夹")

        self.file_menu.addSeparator()

        self.file_menu.addAction("保存")
        self.file_menu.addAction("另存为")
        self.file_menu.addAction("全部保存")

        self.file_menu.addSeparator()

        self.file_menu.addAction("退出")

        self.label = QLabel(window)                                             # 9.创建标签控件
        layout.addWidget(self.label)                                            # 10.添加标签控件到布局中

  修改 widget.py 文件的内容。

import sys

from PySide6.QtWidgets import QApplication, QWidget
from PySide6.QtGui import QAction

from ui import MyUi

class MyWidget(QWidget):
    def __init__(self):
        super().__init__()                                                      # 1.调用父类Qwidget类的__init__()方法
      
        self.__ui = MyUi()
        self.__ui.setupUi(self)                                                # 2.初始化页面

        self.__ui.menuBar.hovered.connect(self.menuBar_hovered)                 # 3.鼠标悬停菜单时触发信号
        self.__ui.menuBar.triggered.connect(self.menuBar_triggered)             # 4.动作被激活时触发信号

    def menuBar_hovered(self, action:QAction):
        text = f"你悬停在【{action.text()}】菜单项"
        self.__ui.label.setText(text)

    def menuBar_triggered(self, action:QAction):
        text = f"你点击了【{action.text()}】菜单项"
        self.__ui.label.setText(text)

if __name__ == "__main__":
    app = QApplication(sys.argv)                                                # 1.创建一个QApplication类的实例
    window = MyWidget()                                                         # 2.创建一个窗口
    window.show()                                                               # 3.显示窗口
    sys.exit(app.exec())                                                        # 4.进入程序的主循环并通过exit()函数确保主循环安全结束

2.2、菜单

  菜单 QMenu 用于 放置动作和子菜单,通常将动作分类放到不同的菜单中。菜单 QMenu 继承自 QWidget。用 QMenu 类创建菜单实例的方法如下所示:

QMenu(parent:QWidget=None)
QMenu(title:str, parent:QWidget=None)

  QMenu 类表示菜单栏中的菜单,可以显示文本和图标,但是并不负责执行操作,类似于 QLable 的作用。

  QMenu 类的常用方法如下:

# 实例方法
addMenu(menu:QMenu) -> QAction                                                  # 在菜单中添加子菜单
addMenu(title:str) -> QMenu                                                     # 在菜单中添加新子菜单
addMenu(icon:QIcon, title:str) -> QMenu                                         # 在菜单中添加新子菜单

insertMenu(before:QAction, menu:QMenu) -> QAction                               # 在指定的动作之前插入菜单

addAction(action:QAction) -> None                                               # 在菜单中添加已经存在的动作
addAction(text:str) -> QAction                                                  # 在菜单中添加新动作
addAction(icon:QIcon, title:str) -> QAction                                     # 在菜单中添加新动作

addSeparator() -> QAction                                                       # 添加分隔符
addSection(text:str) -> QAction                                                 # 添加分隔符
addSection(icon:QIcon, text:str) -> QAction                                     # 添加分隔符

insertSeparator(before:QAction) -> QAction                                      # 在指定的动作之前插入分隔符
insertSection(before:QAction, text:str) -> QAction                              # 在指定的动作之前插入分隔符
insertSection(before:QAction, icon:QIcon, text:str) -> QAction                  # 在指定的动作之前插入分隔符

removeAction(action:QAction) -> None                                            # 从菜单中删除动作

clear() -> None                                                                 # 清空菜单
isEmpty() -> bool                                                               # 判断菜单是否为空

actions() -> List[QAction]                                                      # 获取动作列表
actionAt(point:QPoint) -> QAction                                               # 获取指定位置的动作

columnCount() -> int                                                            # 获取列数
menuAction() -> QAction                                                         # 获取菜单动作

setSeparatorsCollapsible(collapse:bool) -> None                                 # 设置是否可以折叠分隔符
setTearOffEnabled(enable:bool) -> None                                          # 设置是否可以拖动分隔符

showTearOffMenu() -> None                                                       # 以拖动方式显示菜单
showTearOffMenu(pos:QPoint) -> None                                             # 以拖动方式显示菜单

hideTearOffMenu() -> None                                                       # 隐藏拖动菜单

isTearOffEnabled() -> bool                                                      # 判断是否可以拖动分隔符
isTearOffMenuVisible() -> bool                                                  # 判断是否显示拖动菜单

setTitle(title:str) -> None                                                     # 设置菜单标题
title() -> str                                                                  # 获取菜单标题

setIcon(icon:QIcon) -> None                                                     # 设置菜单图标
icon() -> QIcon                                                                 # 获取菜单图标

setActiveAction(action:QAction) -> None                                         # 设置活跃的动作高亮显示
activeAction() -> QAction                                                       # 获取活跃的动作

setDefaultAction(action:QAction) -> None                                        # 设置默认动作
defaultAction() -> QAction                                                      # 获取默认动作

popup(pos:QPoint, at:QAction=None) -> None                                      # 弹出菜单

# 静态方法
exec(actions:Sequence[QAction], pos:QPoint, at:QAction=None, parent:QWidget=None)   # 在指定位置显示菜单,当pos无法确定位置时,用父控件的parent辅助确定位置

  QMenu 类常用的信号及其说明如下:

aboutToHide()                                                                   # 窗口即将隐藏时发射信号
aboutToShow()                                                                   # 窗口即将显示时发射信号
hovered(action:QAction)                                                         # 鼠标悬停时发射信号
triggered(action:QAction)                                                       # 鼠标单击时发射信号

  修改 ui.py 文件的内容。

from PySide6.QtWidgets import QWidget
from PySide6.QtWidgets import QMenuBar, QMenu, QLabel
from PySide6.QtWidgets import QVBoxLayout

class MyUi:
    def setupUi(self, window:QWidget):
        window.resize(800, 600)                                                 # 1.设置窗口对象大小

        layout = QVBoxLayout(window)                                            # 2.创建一个垂直布局

        self.menuBar = QMenuBar(window)                                         # 3.创建菜单栏
        self.menuBar.setFixedHeight(30)                                         # 4.设置菜单栏宽度
        layout.addWidget(self.menuBar)                                          # 5.添加菜单栏到布局中

        self.file_menu = QMenu()                                                # 6.创建菜单
        self.menuBar.addMenu(self.file_menu)                                    # 7.将菜单添加到菜单栏中
        self.file_menu.setTitle("文件(&F)")                                      # 8.设置菜单标题

        self.file_menu.addAction("新建文件")                                      # 9.向菜单中添加动作
        self.file_menu.addAction("新建文件夹")

        self.file_menu.addSeparator()                                           # 10.添加分隔符

        self.file_menu.addAction("打开文件")
        self.file_menu.addAction("打开文件夹")

        self.file_menu.addSeparator()

        self.file_menu.addAction("保存")
        self.file_menu.addAction("另存为")
        self.file_menu.addAction("全部保存")

        self.file_menu.addSeparator()

        self.file_menu.addAction("退出")

        self.label = QLabel(window)                                             # 11.创建标签控件
        layout.addWidget(self.label)                                            # 12.添加标签控件到布局中

  修改 widget.py 文件的内容。

import sys

from PySide6.QtWidgets import QApplication, QWidget
from PySide6.QtGui import QAction

from ui import MyUi

class MyWidget(QWidget):
    def __init__(self):
        super().__init__()                                                      # 1.调用父类Qwidget类的__init__()方法
      
        self.__ui = MyUi()
        self.__ui.setupUi(self)                                                # 2.初始化页面

        self.__ui.file_menu.aboutToShow.connect(self.menu_about_to_show)        # 3.菜单将要被显示时触发信号
        self.__ui.file_menu.aboutToHide.connect(self.menu_about_to_hide)        # 4.菜单将要被隐藏时触发信号
        self.__ui.file_menu.hovered.connect(self.menu_hovered)                  # 5.鼠标悬停菜单时触发信号
        self.__ui.file_menu.triggered.connect(self.menu_triggered)              # 6.动作被激活时触发信号

    def menu_about_to_show(self):
        self.__ui.label.setText("菜单将要被显示")

    def menu_about_to_hide(self):
        self.__ui.label.setText("菜单将要被隐藏")

    def menu_hovered(self, action:QAction):
        text = f"你悬停在【{action.text()}】菜单项"
        self.__ui.label.setText(text)

    def menu_triggered(self, action:QAction):
        text = f"你点击了【{action.text()}】菜单项"
        self.__ui.label.setText(text)

if __name__ == "__main__":
    app = QApplication(sys.argv)                                                # 1.创建一个QApplication类的实例
    window = MyWidget()                                                         # 2.创建一个窗口
    window.show()                                                               # 3.显示窗口
    sys.exit(app.exec())                                                        # 4.进入程序的主循环并通过exit()函数确保主循环安全结束

2.3、动作

  动作 QAction 是定义菜单和工具栏的基础,单击菜单或工具栏上的动作可以触发动作的 triggered() 信号,执行动作关联的槽函数,完成需要完成的工作。动作在菜单中以项(item)的形式显示,在工具栏中以按钮的形式显示。

  动作 QAction 继承自 QObject,位于 QtGui 模块中。用 QAction 创建动作对象的方法如下所示:

QAction(parent:QObject=None)
QAction(text:str, parent:QObject=None)
QAction(icon:Union[QIcon, QPixmap], text:str, parent:QObject=None)

  其中 parent 通常是 窗口工具栏菜单栏菜单text显示的文字,如果将动作放到菜单或工具栏上,text 将成为菜单或工具栏中按钮的文字;icon图标,将成为菜单或工具栏中按钮的图标。

  QAction 类的常用方法如下:

# 实例方法
setText(text:str) -> None                                                       # 设置菜单项文本
text() -> str                                                                   # 获取菜单项文本

setIcon(icon:QIcon) -> None                                                     # 设置菜单项的图标
icon() -> QIcon                                                                 # 获取菜单项图标

setIconVisibleInMenu(visible:bool) -> None                                      # 设置图标是否显示在菜单中
isIconVisibleInMenu() -> bool                                                   # 获取图标是否显示在菜单中

setData(data:Any) -> None                                                       # 设置菜单项数据
data() -> Any                                                                   # 获取菜单项数据

setToolTip(tip:str) -> None                                                     # 设置菜单项提示
setStatusTip(statusTip:str) -> None                                             # 设置状态提示
setWhatsThis(what:str) -> None                                                  # 设置按Shift+F1键时的提示

setCheckable(checkable:bool) -> None                                            # 设置菜单项是否可选
isCheckable() -> bool                                                           # 获取菜单项是否可选
isChecked() -> bool                                                             # 获取菜单项是否选中

isEnabled() -> bool                                                             # 获取菜单项是否可用
isVisible() -> bool                                                             # 获取菜单项是否可见

setShortcutVisibleInContextMenu(show:bool) -> None                              # 设置快捷键是否显示在右键菜单中
setShortcuts(key:QKeySequence) -> None                                          # 设置快捷键
setShortcuts(shortcuts:QKeySequence.StandardKey)                                # 设置快捷键

setFont(font:QFont) -> None                                                     # 设置菜单项字体
font() -> QFont                                                                 # 获取菜单项字体
setMenu(menu:QMenu) -> None                                                     # 设置菜单项的子菜单
menu() -> QMenu                                                                 # 获取菜单项的子菜单

setActionGroup(group:QActionGroup) -> None                                      # 设置菜单项的动作组

setSeparator(enable:bool) -> None                                               # 设置菜单项是否为分隔符

setAutoRepeat(repeat:bool) -> None                                              # 设置菜单项是否自动重复
autoRepeat() -> bool                                                            # 获取菜单项是否自动重复

# 槽方法
setChecked(checked:bool) -> None                                                # 设置菜单项是否选中
setEnabled(enabled:bool) -> None                                                # 设置菜单项是否可用
setDisabled(disabled:bool) -> None                                              # 设置菜单项是否失效
setVisible(visible:bool) -> None                                                # 设置菜单项是否可见

resetEnabled() -> None                                                          # 重置菜单项是否可用

hover() -> None                                                                 # 发送hover()信号
trigger() -> None                                                               # 发送tigger(bool)信号
toggle() -> None                                                                # 发送toggle(bool)信号

  QAction 类常用信号及其说明如下:

changed()                                                                       # 改变时发射信号
checkableChanged(checkable:bool)                                                # 可选状态改变时发射信号
enabledChanged(enabled:bool)                                                    # 启用状态改变时发射信号
hovered()                                                                       # 鼠标悬停时发射信号
toggled(arg__1:bool)                                                            # 状态翻转时发射信号
triggered(checked:bool=false)                                                   # 鼠标单击时发射信号
visibleChanged()                                                                # 可见状态改变时发射信号

  对于互斥的一些动作,需要将其放到一个组中,可以先用 group=QActionGroup(parent:QWidget) 创建一个对象,然后用 group.addAction(action:QAction) 方法把动作放到一个组中,并将 setExclusive(exclusive:bool) 设置成True,这样就可以保证组内的动作是互斥的。

  修改 ui.py 文件的内容。

from PySide6.QtWidgets import QWidget
from PySide6.QtWidgets import QMenuBar, QMenu, QLabel
from PySide6.QtWidgets import QVBoxLayout
from PySide6.QtGui import QAction, QKeySequence

class MyUi:
    def setupUi(self, window:QWidget):
        window.resize(800, 600)                                                 # 1.设置窗口对象大小

        layout = QVBoxLayout(window)                                            # 2.创建一个垂直布局

        self.menuBar = QMenuBar(window)                                         # 3.创建菜单栏
        self.menuBar.setFixedHeight(30)                                         # 4.设置菜单栏宽度
        layout.addWidget(self.menuBar)                                          # 5.添加菜单栏到布局中

        self.file_menu = QMenu("文件(&F)")                                       # 6.创建菜单
        self.menuBar.addMenu(self.file_menu)                                    # 7.将菜单添加到菜单栏中

        self.new_file_action = QAction("新建文件")                                # 8.创建动作
        self.file_menu.addAction(self.new_file_action)                          # 9.将动作添加到菜单中
        self.new_file_action.setShortcut("Ctrl+N")                              # 10.设置快捷键

        self.new_folder_action = QAction("新建文件夹")
        self.file_menu.addAction(self.new_folder_action)

        self.file_menu.addSeparator()                                           # 11.添加分隔符

        self.open_file_action = QAction("打开文件")
        self.open_file_action.setShortcut(QKeySequence.StandardKey.Open)
        self.open_file_action.setShortcutVisibleInContextMenu(True)             # 12.设置快捷键可见

        self.open_folder_action = QAction("打开文件夹")

        self.file_menu.addActions([self.open_file_action, self.open_folder_action]) # 13.将动作列表添加到菜单中

        self.file_menu.addSeparator()

        self.save_action = QAction("保存", shortcut=QKeySequence.fromString("Ctrl+S"), shortcutVisibleInContextMenu=True)
        self.save_as_action = QAction("另存为", shortcut=QKeySequence.fromString("Ctrl+Shift+S"), shortcutVisibleInContextMenu=True)
        self.save_all_action = QAction("全部保存")
        self.file_menu.addActions([self.save_action, self.save_as_action, self.save_all_action])

        self.file_menu.addSeparator()

        self.exit_action = QAction("退出", shortcut=QKeySequence.fromString("Ctrl+Q"), shortcutVisibleInContextMenu=True)
        self.file_menu.addAction(self.exit_action)

        self.label = QLabel(window)                                             # 14.创建标签控件
        layout.addWidget(self.label)                                            # 15.添加标签控件到布局中

  修改 widget.py 文件的内容。

import sys

from PySide6.QtWidgets import QApplication, QWidget
from PySide6.QtGui import QAction

from ui import MyUi

class MyWidget(QWidget):
    def __init__(self):
        super().__init__()                                                      # 1.调用父类Qwidget类的__init__()方法
      
        self.__ui = MyUi()
        self.__ui.setupUi(self)                                                 # 2.初始化页面

        self.__ui.new_file_action.hovered.connect(lambda:self.action_hovered(self.__ui.new_file_action))      # 4.鼠标悬停菜单时触发信号
        self.__ui.new_file_action.triggered.connect(lambda:self.action_triggered(self.__ui.new_file_action))  # 5.点击菜单时触发信号

        self.__ui.new_folder_action.hovered.connect(lambda:self.action_hovered(self.__ui.new_folder_action))
        self.__ui.new_folder_action.triggered.connect(lambda:self.action_triggered(self.__ui.new_folder_action))

        self.__ui.open_file_action.hovered.connect(lambda:self.action_hovered(self.__ui.open_file_action))
        self.__ui.open_file_action.triggered.connect(lambda:self.action_triggered(self.__ui.open_file_action))

        self.__ui.open_folder_action.hovered.connect(lambda:self.action_hovered(self.__ui.open_folder_action))
        self.__ui.open_folder_action.triggered.connect(lambda:self.action_triggered(self.__ui.open_folder_action))

        self.__ui.save_action.hovered.connect(lambda:self.action_hovered(self.__ui.save_action))
        self.__ui.save_action.triggered.connect(lambda:self.action_triggered(self.__ui.save_action))

        self.__ui.save_as_action.hovered.connect(lambda:self.action_hovered(self.__ui.save_as_action))
        self.__ui.save_as_action.triggered.connect(lambda:self.action_triggered(self.__ui.save_as_action))

        self.__ui.save_all_action.hovered.connect(lambda:self.action_hovered(self.__ui.save_all_action))
        self.__ui.save_all_action.triggered.connect(lambda:self.action_triggered(self.__ui.save_all_action))

        self.__ui.exit_action.hovered.connect(lambda:self.action_hovered(self.__ui.exit_action))
        self.__ui.exit_action.triggered.connect(lambda:self.action_triggered(self.__ui.exit_action))

    def action_hovered(self, action:QAction):
        text = f"你悬停在【{action.text()}】菜单项"
        self.__ui.label.setText(text)

    def action_triggered(self, action:QAction):
        text = f"你点击了【{action.text()}】菜单项"
        self.__ui.label.setText(text)

if __name__ == "__main__":
    app = QApplication(sys.argv)                                                # 1.创建一个QApplication类的实例
    window = MyWidget()                                                         # 2.创建一个窗口
    window.show()                                                               # 3.显示窗口
    sys.exit(app.exec())                                                        # 4.进入程序的主循环并通过exit()函数确保主循环安全结束

在使用 PySide6 中的菜单时,只有 QAction 菜单项可以执行操作,QMenuBar 菜单栏和 QMenu 菜单都是不会执行任何操作的。

三、工具栏

  与菜单类似,工具栏也是一组命令的集合地。菜单上放置的动作也可放到工具栏上,实现工具栏和菜单的同步。工具栏上除了放置动作外,还可以放置其他控件等。

  工具栏 QToolBar 用于存放动作,动作在工具栏中一般呈现按钮状态。QToolBar 继承自 QWidget。用 QToolBar 类创建工具栏实例的方法如下:

QToolBar(parent:QWidget=None)
QToolBar(title:str, parent:QWidget=None)

  其中 title 是工具栏控件的 标题名称,可通过 setWindowTitle(title:str) 方法修改;parent 是工具栏所在的 窗口

  QToolBar 类常用方法如下:

# 实例方法
addAction(action:QAction) -> None                                               # 添加已经存在的动作到工具栏
addAction(text:str) -> QAction                                                  # 创建并添加动作,返回新建立的动作
addAction(icon:QIcon, title:str) -> QAction                                     # 创建并添加动作,返回新建立的动作

addSeparator() -> QAction                                                       # 添加分隔符
insertSeparator(before:QAction) -> QAction                                      # 在指定的动作之前插入分隔符

addWidget(widget:QWidget) -> QAction                                            # 添加控件,并返回与控件关联的动作
insertWidget(before:QAction, widget:QWidget) -> QAction                         # 在指定的动作之前插入控件,并返回与控件关联的动作

clear() -> None                                                                 # 清空菜单

widgetForAction(action:QAction) -> QWidget                                      # 返回与动作关联的控件

actionAt(x:int, y:int) -> QAction                                               # 返回指定位置处的动作
actionAt(p:QPoint) -> QAction                                                   # 返回指定位置处的动作
actionGeometry(action:QAction) -> QRect                                         # 返回指定动作的矩形区域

setFloatable(floatable:bool) -> None                                            # 设置动作是否可以浮在其他窗口上
isFloatable() -> bool                                                           # 返回动作是否可以浮在其他窗口上
isFloating() -> bool                                                            # 返回动作是否浮在其他窗口上
setMovable(movable:bool) -> None                                                # 设置动作是否可以移动
isMovable() -> bool                                                             # 返回动作是否可以移动

iconSize () -> QSize                                                            # 返回动作图标大小

setOrientation(orientation:Qt.Orientation) -> None                              # 设置动作的方向
orientation() -> Qt.Orientation                                                 # 返回动作的方向

toolButtonStyle() -> Qt.ToolButtonStyle                                         # 返回动作样式

setAllowedAreas(areas:Qt.ToolButtonArea) -> None                                # 设置可停靠的区域
allowedAreas() -> Qt.ToolButtonArea                                             # 获取可停靠的区域
isAreaAllowed(area:Qt.ToolButtonArea) -> bool                                   # 获取指定的区域是否可以停靠
toggleViewAction() -> QAction                                                   # 切换停靠窗口的可见状态

# 槽函数
setIconSize(iconSize:QSize) -> None                                             # 设置动作图标大小
setToolButtonStyle(toolButtonStyle:Qt.ToolButtonStyle) -> None                  # 设置动作样式

  QToolBar 类常用信号及其说明如下:

actionTriggered(action:QAction)                                                 # 工具栏按钮被触发时发射信号
allowedAreasChanged(allowedAreas:Qt.ToolBarArea)                                # 工具栏按钮显示区域改变时发射信号
iconSizeChanged(iconSize:QSize)                                                 # 工具栏按钮图标大小改变时发射信号
movableChanged(movable:bool)                                                    # 工具栏移动时发射信号
orientationChanged(orientation:Qt.Orientation)                                  # 工具栏按钮显示的方向改变时发射信号
toolButtonStyleChanged(toolButtonStyle:Qt.ToolButtonStyle)                      # 文本显示样式改变时发射信号
topLevelChanged(topLevel:bool)                                                  # 工具栏浮动属性改变时发射信号
visibilityChanged(visible:bool)                                                 # 工具栏按钮是否可见改变时发射信号

  用 setOrientation(orientation:Qt.Orientation) 方法可以 设置工具栏的方向,其中 Qt.Orientation 可以取值如下:

Qt.Orientation.Horizontal                                                       # 水平
Qt.Orientation.Vertical                                                         # 竖直

  用 setToolButtonStyle(style:Qt.ToolButtonStyle) 方法可以 设置工具栏上按钮的风格,其中 Qt.ToolButtonStyle 枚举值可以取值如下:

Qt.ToolButtonStyle.ToolButtonIconOnly                                           # 只显示图标
Qt.ToolButtonStyle.ToolButtonTextOnly                                           # 只显示文字
Qt.ToolButtonStyle.ToolButtonTextBesideIcon                                     # 文字在图标的旁边
Qt.ToolButtonStyle.ToolButtonTextUnderIcon                                      # 文字在图标的下面
Qt.ToolButtonStyle.ToolButtonFollowStyle                                        # 遵循风格设置

  用 toggleViewAction() 方法返回一个动作对象,通过单击该动作对象可以切换停靠窗口的可见状态,即该动作是一个对停靠控件窗口进行显示或关闭的开关,如果将该动作加到菜单上,对应菜单栏的文字即为停靠窗口的标题名称,这样就可以在菜单上单击对应菜单项进行停靠窗口的关闭和显示。

  修改 ui.py 文件的内容。

from PySide6.QtWidgets import QWidget
from PySide6.QtWidgets import QToolBar, QToolButton, QMenu
from PySide6.QtWidgets import QComboBox, QLabel
from PySide6.QtWidgets import QVBoxLayout
from PySide6.QtGui import Qt, QIcon, QAction

class MyUi:
    def setupUi(self, window:QWidget):
        window.resize(800, 600)                                                 # 1.设置窗口对象大小

        layout = QVBoxLayout(window)                                            # 2.创建一个垂直布局

        self.toolBar = QToolBar()                                               # 3.创建一个工具栏,并添加到布局中
        layout.addWidget(self.toolBar)

        self.toolBar.setToolButtonStyle(Qt.ToolButtonStyle.ToolButtonTextUnderIcon) # 4.设置工具栏的显示样式
        self.toolBar.setOrientation(Qt.Orientation.Horizontal)                      # 5.设置工具栏的方向

        new_action = QAction(QIcon("assets/images/1.ico"), "新建", self.toolBar)    # 6.创建动作,并添加到工具栏中
        open_action = QAction(QIcon("assets/images/1.ico"), "打开", self.toolBar)
        save_action = QAction(QIcon("assets/images/1.ico"), "保存", self.toolBar)
        close_action = QAction(QIcon("assets/images/1.ico"), "关闭", self.toolBar)
        self.toolBar.addActions([new_action, open_action, save_action, close_action])

        comboBox = QComboBox()                                                  # 7.添加其它组件到工具栏中
        self.toolBar.addWidget(comboBox)
        names = ["木之本樱", "御坂美琴", "夏娜"]
        comboBox.addItems(names)

        toolButton = QToolButton(self.toolBar)                                  # 8.创建工具按钮,并添加工具按钮到工具栏中
        self.toolBar.addWidget(toolButton)

        toolButton.setArrowType(Qt.ArrowType.RightArrow)                        # 9.设置工具按钮的箭头样式
        toolButton.setText("文件")                                               # 10.设置工具按钮的文本
        toolButton.setToolButtonStyle(Qt.ToolButtonStyle.ToolButtonTextBesideIcon)  # 11.设置工具按钮的样式
        toolButton.setPopupMode(QToolButton.ToolButtonPopupMode.MenuButtonPopup)    # 12.设置工具按钮菜单弹出模式

        menu = QMenu("文件", toolButton)                                         # 13.创建菜单,并添加到工具按钮控件中
        toolButton.setMenu(menu)
        menu.addActions([new_action, open_action, save_action, close_action])   # 14.往菜单中添加动作

        self.label = QLabel(window)                                             # 15.创建标签控件
        layout.addWidget(self.label)                                            # 16.添加标签控件到布局中

  修改 widget.py 文件的内容。

import sys

from PySide6.QtWidgets import QApplication, QWidget
from PySide6.QtGui import QAction

from ui import MyUi

class MyWidget(QWidget):
    def __init__(self):
        super().__init__()                                                      # 1.调用父类Qwidget类的__init__()方法
      
        self.__ui = MyUi()
        self.__ui.setupUi(self)                                                 # 2.初始化页面

        self.__ui.toolBar.actionTriggered.connect(self.toolBar_action_triggered)    # 3.动作被激活时触发信号

    def toolBar_action_triggered(self, action:QAction):
        self.__ui.label.setText(f"你点击了【{action.text()}】按钮")

if __name__ == "__main__":
    app = QApplication(sys.argv)                                                # 1.创建一个QApplication类的实例
    window = MyWidget()                                                         # 2.创建一个窗口
    window.show()                                                               # 3.显示窗口
    sys.exit(app.exec())                                                        # 4.进入程序的主循环并通过exit()函数确保主循环安全结束

如果设置垂直工具栏没有效果,那可能是你先调用 setOrientation(orientation:Qt.Orientation) 设置工具栏方向,在将工具栏添加到窗体中。

单击工具栏中的 QAction 对象默认会发送 actionTriggered 信号,但是如果为工具栏添加了其它控件,并不会发射 actionTriggered 信号,而是会发射它们自己的特有信号。

四、状态栏

  状态栏 QStatusBar 一般放在独立窗口的底部,用于 显示程序运行过程中的程序状态信息、提示信息、简要说明信息等,这些信息经过一小段时间后会自动消失。状态栏上也可以放置一些小控件等,用于显示永久信息,永久信息不会被实时信息遮挡住。

  状态栏 QStatusBar 继承自 QWidget。用 QStatusBar 类创建状态栏实例的方法如下:

QStatusBar(parent:QWidget=None)

  其中 parent 是状态的 父窗口,一般是独立窗口。

  QStatusBar 类常用方法及其说明如下:

# 实例方法
urrentMessage() -> str                                                          # 获取当前显示的信息

addWidget(widget:QWidget, stretch:int=0) -> None                                # 在状态栏的左侧添加临时的控件,stretch是拉伸比例
insertWidget(index:int, widget:QWidget, stretch:int=0) -> None                  # 在状态栏的左侧插入临时的控件,stretch是拉伸比例

addPermanentWidget(widget:QWidget, stretch:int=0) -> None                       # 在状态栏的右侧添加永久性的控件,stretch是拉伸比例
insertPermanentWidget(index:int, widget:QWidget, stretch:int=0) -> None         # 在状态栏的右侧插入永久性的控件,stretch是拉伸比例

removeWidget(widget:QWidget) -> None                                            # 从状态栏中移除控件

setSizeGripEnabled(enable:bool) -> None                                         # 设置在右下角是否有三角形
isSizeGripEnabled() -> bool                                                     # 获取右下角是否有三角形

hideOrShow() -> None                                                            # 确保右边的控件可见

# 槽函数
showMessage(text:str, timeout:int=0) -> None                                    # 显示信息,timeout是显示时间
clearMessage() -> None                                                          # 清空信息

  QStatusBar 类常用信号及其说明如下:

messageChanged(text:str)                                                        # 消息改变时发送信号                                  

  用 showMessage(text:str, timeout:int=0) 方法 设置状态栏要显示的信息,显示的信息从状态的左侧开始,其中参数 timeout 的单位是 毫秒设置信息显示的时间,经过 timeout 毫秒后信息自动消失,如果 timeout = 0,则显示的信息一直保留到调用 clearMessage() 方法或再次调用 showMessage() 方法;

  用 addtWidget(widget:QWidget, stretch:int=0) 方法或 insertWidget(index:int, widget:QWidget, stretch:int=0) 方法可以 把其它控件添加到状态栏的左侧,用于显示正常的信息,这些信息会被状态栏的信息遮挡住。

  用 addPermanentWidget(widget:QWidget, stretch:int=0) 方法或 insertPermanentWidget(index:int, widget:QWidget, stretch:int=0) 方法可以 把其它控件添加到状态栏的右侧,用于 显示一些永久的信息。其中参数 stretch 用于 指定控件的相对缩放系数index控件的索引号

  用 removeWidget(widget:QWidget) 方法可以 把控件从状态栏上移除,但控件并没有被真正删除,可以用 addWidget(widget:Widget) 方法和 show() 方法将控件重新添加到状态栏中。

  修改 ui.py 文件的内容。

from PySide6.QtWidgets import QWidget
from PySide6.QtWidgets import QStatusBar
from PySide6.QtWidgets import QComboBox, QLabel
from PySide6.QtWidgets import QVBoxLayout

class MyUi:
    def setupUi(self, window:QWidget):
        window.resize(800, 600)                                                 # 1.设置窗口对象大小

        layout = QVBoxLayout(window)                                            # 2.创建一个垂直布局

        self.label = QLabel(window)                                             # 3.创建标签控件
        layout.addWidget(self.label)                                            # 4.添加标签控件到布局中

        self.statusBar = QStatusBar(window)                                     # 5.创建一个状态栏
        self.statusBar.setFixedHeight(30)                                       # 6.设置状态栏的高度
        layout.addWidget(self.statusBar)                                        # 7.添加状态栏控件到布局中

        comboBox = QComboBox()                                                  # 8.向状态栏中添加控件
        names = ["木之本樱", "御坂美琴", "夏娜"]
        comboBox.addItems(names)
        self.statusBar.addPermanentWidget(comboBox)

  修改 widget.py 文件的内容。

import sys

from PySide6.QtWidgets import QApplication, QWidget
from PySide6.QtCore import QTimer, QDateTime

from ui import MyUi

class MyWidget(QWidget):
    def __init__(self):
        super().__init__()                                                      # 1.调用父类Qwidget类的__init__()方法
      
        self.__ui = MyUi()
        self.__ui.setupUi(self)                                                 # 2.初始化页面

        timer = QTimer(self)                                                    # 3.创建一个QTime定时器对象
        timer.start(1000)                                                       # 4.启动定时器

        timer.timeout.connect(self.update_time)                                 # 5.定时器定时时间到触发

        self.__ui.statusBar.messageChanged.connect(self.statusBar_message_changed)  # 6.状态栏消息改变时触发

    def update_time(self):
        datatime = QDateTime.currentDateTime()                                  # 1.获取当前日期时间
        text = datatime.toString("yyyy-MM-dd HH:mm:ss")                         # 2.对日期时间进行格式化
        self.__ui.statusBar.showMessage(f"当前日期时间: {text}")                 # 3.在状态栏中显示一条临时消息

    def statusBar_message_changed(self, text:str):
        self.__ui.label.setText(text)                                           # 1.设置标签的文本

if __name__ == "__main__":
    app = QApplication(sys.argv)                                                # 1.创建一个QApplication类的实例
    window = MyWidget()                                                         # 2.创建一个窗口
    window.show()                                                               # 3.显示窗口
    sys.exit(app.exec())                                                        # 4.进入程序的主循环并通过exit()函数确保主循环安全结束

默认情况下,状态栏中的临时消息和添加的控件不能同时显示,否则会发生覆盖重合的情况。此时,我们可以使用 addPermanentWidget(widget:QWidget, stretch:int=0) 添加永久性控件来解决。

posted @ 2025-01-09 19:12  星光映梦  阅读(160)  评论(0)    收藏  举报