PyQt5 - 多文档界面

一个典型的 GUI 应用程序可能有多个窗口。 选项卡式和堆叠式小部件允许一次激活一个这样的窗口。 然而,很多时候这种方法可能没有用,因为其他窗口的视图被隐藏了。

同时显示多个窗口的一种方法是将它们创建为独立的窗口。 这称为 SDI (单文档接口)。 这需要更多的内存资源,因为每个窗口可能有自己的菜单系统、工具栏等。

MDI (多文档接口) 应用程序消耗较少的内存资源。 子窗口相对于彼此放置在主容器内。 容器小部件称为 QMdiArea

QMdiArea 小部件一般占据 QMainWondow 对象的中心小部件。 该区域中的子窗口是 QMdiSubWindow 类的实例。 可以将任何 QWidget 设置为 subWindow 对象的内部小部件。 MDI区域的子窗口可以层叠或平铺排列。

下表列出了QMdiArea类和QMdiSubWindow类的重要方法 −

序号 方法 & 说明
1

addSubWindow()

在 MDI 区域中添加一个小部件作为新的子窗口

2

removeSubWindow()

删除作为子窗口内部小部件的小部件

3

setActiveSubWindow()

激活子窗口

4

cascadeSubWindows()

以级联方式排列 MDiArea 中的子窗口

5

tileSubWindows()

以平铺方式排列 MDiArea 中的子窗口

6

closeActiveSubWindow()

关闭活动子窗口

7

subWindowList()

返回 MDI 区域中的子窗口列表

8

setWidget()

将 QWidget 设置为 QMdiSubwindow 实例的内部小部件

QMdiArea 对象发出 subWindowActivated() 信号,而 windowStateChanged() 信号由 QMdisubWindow 对象发出。


示例

在下面的示例中,由 QMainWindow 组成的顶级窗口有一个菜单和 MdiArea。

self.mdi = QMdiArea()
self.setCentralWidget(self.mdi)
bar = self.menuBar()
file = bar.addMenu("File")

file.addAction("New")
file.addAction("cascade")
file.addAction("Tiled")

菜单的 Triggered() 信号连接到 windowaction() 函数。

file.triggered[QAction].connect(self.windowaction)

menu 的新动作在 MDI 区域中添加了一个子窗口,其标题具有递增编号。

MainWindow.count = MainWindow.count+1
sub = QMdiSubWindow()
sub.setWidget(QTextEdit())
sub.setWindowTitle("subwindow"+str(MainWindow.count))
self.mdi.addSubWindow(sub)
sub.show()

菜单的级联和平铺按钮分别以级联和平铺方式排列当前显示的子窗口。

完整代码如下 −

import sys
from PyQt5.QtCore import *
from PyQt5.QtGui import *
from PyQt5.QtWidgets import *

class MainWindow(QMainWindow):
   count = 0

   def __init__(self, parent = None):
      super(MainWindow, self).__init__(parent)
      self.mdi = QMdiArea()
      self.setCentralWidget(self.mdi)
      bar = self.menuBar()

      file = bar.addMenu("File")
      file.addAction("New")
      file.addAction("cascade")
      file.addAction("Tiled")
      file.triggered[QAction].connect(self.windowaction)
      self.setWindowTitle("MDI demo")

   def windowaction(self, q):
      print ("triggered")
   
      if q.text() == "New":
         MainWindow.count = MainWindow.count+1
         sub = QMdiSubWindow()
         sub.setWidget(QTextEdit())
         sub.setWindowTitle("subwindow"+str(MainWindow.count))
         self.mdi.addSubWindow(sub)
         sub.show()

      if q.text() == "cascade":
         self.mdi.cascadeSubWindows()

      if q.text() == "Tiled":
         self.mdi.tileSubWindows()

def main():
   app = QApplication(sys.argv)
   ex = MainWindow()
   ex.show()
   sys.exit(app.exec_())

if __name__ == '__main__':
   main()

以层叠和平铺的形式运行上面的代码和三个窗口 −

Multiple Document Interface Output1

Multiple Document Interface Output2

Multiple Document Interface Output3