一、什么是MDI窗口
MDI 窗口(Multiple-Document Interface),又称多文档界面,它主要用于同时显示多个文档,每个文档显示在各自的窗口中。MDI 窗口中通常包含子菜单和窗口菜单,用于在窗口或文档之间进行切换。
用 QMainWindow 建立的主界面,通常会同时建立或打开多个相互独立的文档,这些文档共享主界面的菜单、工具栏和停靠控件,多文档中只有一个文档是活跃的文档,菜单和工具栏的操作只针对当前活跃的文档。主界面要实现多文档操作需要用 QMdiArea 控件,通常把 QMdiArea 定义成中心控件。可以在 QMdiArea 控件中添加多个子窗口 QMdiSubWindow,通常每个子窗口都有相同的控件,当然控件也可以不相同。
我们可以在终端中使用 pip 安装 pyside6 模块。
pip install pyside6
多文档区 QMdiArea 和子窗口 QMdiSubWindow 的继承关系如下所示:
用 QMdiArea 类和 QMdiSubWindow 类创建多文档实例和子窗口实例的方法如下。
QMdiArea(parent:QWidget=None)
QMdiSubWindow(parent:QWidget=None, flags:Qt.WindowFlags=Default(Qt.WindowFlags))
QMidArea 类常用的方法及其说明如下:
# 实例方法
addSubWindow(widget:QWidget, flags:Qt.WindowFlags=Qt.WindowFlags()) -> QMdiSubWindow # 添加子窗口
removeSubWindow(widget:QWidget) -> None # 删除子窗口setViewMode(mode:QMdiArea.ViewMode) -> None # 设置MDI区域的视图模式
viewMode() -> QMdiArea.ViewMode # 获取MDI区域的视图模式currentSubWindow() -> QMdiSubWindow # 获取当前子窗口scrollContentsBy(dx:int, dy:int) -> None # 移动子窗口中的控件
setActivationOrder(order:QMdiArea.WindowOrder) -> None # 设置子窗口的活跃顺序
activationOrder() -> QMdiArea.WindowOrder # 获取子窗口的活跃顺序
subWindowList(order:QMdiArea.WindowOrder=QMdiArea.WindowOrder.CreationOrder) -> List[QMdiSubWindow] # 按照指定顺序获取子窗口列表
activeSubWindow() -> QMdiSubWindow # 获取活跃的子窗口setBackground(background:Union[QBrush, QColor, Qt.GlobalColor, QGradient]) -> None # 设置背景,默认是灰色
background() -> QBrush # 获取背景色画刷
setOption(option:QMdiArea.Option, on:bool=True) -> None # 设置子窗口选项
testOption(opton:QMdiArea.Option) -> bool # 获取子窗口是否设置了选项setTabPosition(position:QTabWidget.TabPosition) -> None # 设置Tab标签的位置
tabPosition() -> QTabWidget.TabPosition # 获取Tab标签的位置
setTabShape(shape:QTabWidget.TabShape) -> None # 设置Tab标签的形状
tabShape() -> QTabWidget.TabShape # 获取Tab标签的形状
setTabsClosable(closable:bool) -> None # 设置Tab标签是否可关闭
tabsClosable() -> bool # 获取Tab标签是否可关闭
setTabsMovable(movable:bool) -> None # 设置Tab标签是否可移动
tabsMovable() -> bool # 获取Tab标签是否可移动
setDocumentMode(enabled:bool) -> None # 设置Tab标签是否为文档模式
documentMode() -> bool # 获取Tab标签是否为文档模式# 槽函数
cascadeSubWindows() -> None # 层叠显示子窗口
tileSubWindows() -> None # 平铺显示子窗口
closeActiveSubWindow() -> None # 关闭正在活动状态的子窗口
closeAllSubWindows() -> None # 关闭全部子窗口
activatePreviousSubWindow() -> None # 激活上一个子窗口
activateNextSubWindow() -> None # 激活下一个子窗口
setActiveSubWindow(window:QMdiSubWindow) -> None # 设置活跃的窗口
QMidArea 类常用的信号及其说明如下:
subWindowActivated(arg__1:QMdiSubWindow) # 当子窗口活跃时发射信号
QMdiSubWindow 类常用的方法及其说明如下:
# 实例方法
setWidget(widget:QWidget) -> None # 设置子窗口的控件
widget() -> QWidget # 获取子窗口的控件
isShaded() -> bool # 获取子窗口是否处于只显示标题栏状态
mdiArea() -> QMdiArea # 返回子窗口所在的多文档区域
setSystemMenu(systemMenu:QMenu) -> None # 设置系统菜单
systemMenu() -> QMenu # 获取系统菜单
setKeyboardPageStep(step:int) -> None # 设置用键盘的Page键控制子窗口移动或缩放时的步长
keyboardPageStep() -> int # 获取用键盘的Page键控制子窗口移动或缩放时的步长
setKeyboardSingleStep(step:int) -> None # 设置用键盘的方向键控制子窗口移动或缩放时的步长
keyboardSingleStep() -> int # 获取用键盘的方向键控制子窗口移动或缩放时的步长
setOption(option:QMdiSubWindow.SubWindowOption, on:bool=true) -> None # 设置选项# 槽函数
showShaded() -> None # 只显示标题
showSystemMenu() -> None # 在标题栏的系统菜单图标下显示系统菜单
QMdiSubWindow 类常用的信号及其说明如下:
aboutToActivate() # 当子窗口活跃时发射信号
windowStateChanged(oldState:Qt.WindowState, newState:Qt.WindowState) # 窗口状态改变时发射信号
import sysfrom PySide6.QtWidgets import QApplication, QMainWindow
from PySide6.QtWidgets import QMdiArea, QMdiSubWindow
from PySide6.QtWidgets import QLabel
from PySide6.QtWidgets import QMenuBar, QMenu
from PySide6.QtGui import QActionclass MyWidget(QMainWindow):def __init__(self):# 1.调用父类Qwidget类的__init__()方法super().__init__()# 2.调用setupUi()方法初始化页面self.setup_ui()def setup_ui(self):# 1.设置窗口对象大小self.resize(700, 500)# 2.创建MDI窗口self.mdiArea = QMdiArea(self)self.mdiArea.setGeometry(0, 0, 700, 500)# 3.创建菜单栏self.menuBar = QMenuBar(self)self.setMenuBar(self.menuBar)# 4.设置菜单self.menu = QMenu("子窗体操作", self)self.menuBar.addMenu(self.menu)# 5.设置菜单项self.new_action = QAction("新建", self.menu)self.tile_action = QAction("平铺显示", self.menu)self.cascade_action = QAction("级联显示", self.menu)self.menu.addActions([self.new_action, self.tile_action, self.cascade_action])# 6.为菜单关联信号self.menuBar.triggered[QAction].connect(self.action)# 7.记录子窗口的个数self.count = 0def action(self, msg):if msg.text() == "新建":# 创建子窗口对象sub = QMdiSubWindow()self.count += 1# 设置子窗口的标题sub.setWindowTitle(f"子窗口{self.count}")# 在子窗口中添加一个标签,并设置文本label = QLabel(f"这是第{self.count}个子窗口")sub.setWidget(label)self.mdiArea.addSubWindow(sub)sub.show()elif msg.text() == "平铺显示":self.mdiArea.tileSubWindows()elif msg.text() == "级联显示":self.mdiArea.cascadeSubWindows()if __name__ == "__main__":# 1.创建一个QApplication类的实例app = QApplication(sys.argv)# 2.创建一个窗口window = MyWidget()# 3.展示窗口window.show()# 4.进入程序的主循环并通过exit()函数确保主循环安全结束sys.exit(app.exec())