Pyqt5 简明教程

PyQt5 - Multiple Document Interface

典型的 GUI 应用程序可能有多个窗口。标签式和小部件可随时激活一个这样的窗口。但是,很多时候此方法可能没有用,因为其他窗口的视图被隐藏了。

A typical GUI application may have multiple windows. Tabbed and stacked widgets allow to activate one such window at a time. However, many a times this approach may not be useful as view of other windows is hidden.

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

One way to display multiple windows simultaneously is to create them as independent windows. This is called as SDI (single Document Interface). This requires more memory resources as each window may have its own menu system, toolbar, etc.

MDI (Multiple Document Interface) 应用程序消耗的内存资源更少。子窗口会放在主容器内,彼此相关。该容器窗口小部件称为 QMdiArea

MDI (Multiple Document Interface) applications consume lesser memory resources. The sub windows are laid down inside main container with relation to each other. The container widget is called QMdiArea.

QMdiArea 小部件通常占用 QMainWondow 对象的中央小部件。此区域内的子窗口是 QMdiSubWindow 类实例。可以将任何 QWidget 设置为 subWindow 对象的内部小部件。MDI 区域内的子窗口可以以层叠或平铺方式进行排列。

QMdiArea widget generally occupies the central widget of QMainWondow object. Child windows in this area are instances of QMdiSubWindow class. It is possible to set any QWidget as the internal widget of subWindow object. Sub-windows in the MDI area can be arranged in cascaded or tile fashion.

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

The following table lists important methods of QMdiArea class and QMdiSubWindow class −

Sr.No.

Methods & Description

1

addSubWindow() Adds a widget as a new subwindow in MDI area

2

removeSubWindow() Removes a widget that is internal widget of a subwindow

3

setActiveSubWindow() Activates a subwindow

4

cascadeSubWindows() Arranges subwindows in MDiArea in a cascaded fashion

5

tileSubWindows() Arranges subwindows in MDiArea in a tiled fashion

6

closeActiveSubWindow() Closes the active subwindow

7

subWindowList() Returns the list of subwindows in MDI Area

8

setWidget() Sets a QWidget as an internal widget of a QMdiSubwindow instance

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

QMdiArea object emits subWindowActivated() signal whereas windowStateChanged() signal is emitted by QMdisubWindow object.

Example

在以下示例中,包含 QMainWindow 的顶级窗口有一个菜单和 MdiArea。

In the following example, top level window comprising of QMainWindow has a menu and 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() 函数。

Triggered() signal of the menu is connected to windowaction() function.

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

菜单的新操作向 MDI 区域中添加子窗口,其标题有一个递增的数字。

The new action of menu adds a subwindow in MDI area with a title having an incremental number to it.

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

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

Cascaded and tiled buttons of the menu arrange currently displayed subwindows in cascaded and tiled fashion respectively.

完整代码如下所示:

The complete code is as follows −

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()

运行以上代码,就会以层叠和平铺形式获得三个窗口−

Run above code and three windows in cascased and tiled formation −

multiple document interface output
multiple document interface outputs
multiple document interface