PyQt: interfaz de varios documentos

Una aplicación de GUI típica puede tener varias ventanas. Los widgets con pestañas y apilados permiten activar una de esas ventanas a la vez. Sin embargo, muchas veces este enfoque puede no ser útil ya que la vista de otras ventanas está oculta.

Una forma de mostrar varias ventanas simultáneamente es crearlas como ventanas independientes. Esto se denomina SDI (interfaz de documento único). Esto requiere más recursos de memoria ya que cada ventana puede tener su propio sistema de menú, barra de herramientas, etc.

Las aplicaciones MDI (Multiple Document Interface) consumen menos recursos de memoria. Las subventanas se colocan dentro del contenedor principal en relación entre sí. El widget contenedor se llamaQMdiArea.

El widget QMdiArea generalmente ocupa el widget central del objeto QMainWondow. Las ventanas secundarias de esta área son instancias de la clase QMdiSubWindow. Es posible configurar cualquier QWidget como el widget interno del objeto subWindow. Las subventanas en el área de MDI pueden disponerse en cascada o en mosaico.

La siguiente tabla enumera los métodos importantes de la clase QMdiArea y la clase QMdiSubWindow:

No Señor. Métodos y descripción
1

addSubWindow()

Agrega un widget como una nueva subventana en el área MDI

2

removeSubWindow()

Elimina un widget que es un widget interno de una subventana.

3

setActiveSubWindow()

Activa una subventana

4

cascadeSubWindows()

Organiza subventanas en MDiArea en cascada

5

tileSubWindows()

Organiza las subventanas en MDiArea en mosaico

6

closeActiveSubWindow()

Cierra la subventana activa

7

subWindowList()

Devuelve la lista de subventanas en el área MDI

8

setWidget()

Establece un QWidget como un widget interno de una instancia de QMdiSubwindow

El objeto QMdiArea emite la señal subWindowActivated () mientras que el objeto QMdisubWindow emite la señal windowStateChanged ().

Ejemplo

En el siguiente ejemplo, la ventana de nivel superior que comprende QMainWindow tiene un menú y MdiArea.

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

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

La señal activada () del menú está conectada a la función de acción de ventana ().

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

La nueva acción de menú agrega una subventana en el área de MDI con un título que tiene un número incremental.

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

Los botones en cascada y en mosaico del menú organizan las subventanas que se muestran actualmente en cascada y en mosaico, respectivamente.

El código completo es el siguiente:

import sys
from PyQt4.QtCore import *
from PyQt4.QtGui 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()

El código anterior produce la siguiente salida: