Una ventana de una aplicación compleja dispone de muchas cosas y entre estas cosas suele haber un menú para poder acceder a la mayor parte de la funcionalidad de la misma de forma ordenada y organizada. En este capítulo describo cómo escribir menús y submenus de la ventana principal y algunas peculiaridades más de Qt.
Índice:
- Instalación de lo que vamos a necesitar.
- Qt, versiones y diferencias.
- Hola, Mundo.
- Módulos en Qt.
- Añadimos icono a la ventana principal.
- Tipos de ventana en un GUI.
- Ventana inicial de carga o Splashscreen.
- Menú principal. Introducción (este capítulo).
- Mejorando algunas cosas vistas.
- Gestión de eventos o Acción y reacción.
- Introducción a Designer.
- Los Widgets vistos a través de Designer: Primera parte.
- Los Widgets vistos a través de Designer: Segunda parte.
- Los widgets vistos a través de Designer: Tercera Parte.
- Los widgets vistos a través de Designer: Cuarta Parte.
- Los widgets vistos a través de Designer: Quinta Parte.
- Los widgets vistos a través de Designer: Sexta parte.
- TBD… (lo actualizaré cuando tenga más claro los siguientes pasos).
[Los materiales para este capítulo los podéis descargar de aquí]
[INSTALACIÓN] Si todavía no has pasado por el inicio del curso, donde explico cómo poner a punto todo, ahora es un buen momento para hacerlo y después podrás seguir con esta nueva receta.
Partimos del último código que dejamos en el capítulo 5 (de momento aparcamos el Splash Screen):
''' Curso de creación de GUIs con Qt5 y Python Author: Kiko Correoso Website: pybonacci.org Licencia: MIT ''' import os os.environ['QT_API'] = 'pyside2' import sys from pathlib import Path from qtpy.QtWidgets import QApplication, QMainWindow from qtpy.QtGui import QIcon class MiVentana(QMainWindow): def __init__(self): super().__init__() self._create_ui() def _create_ui(self): self.resize(500, 300) self.move(0, 0) self.setWindowTitle('Hola, QMainWindow') ruta_icono = Path('.', 'imgs', 'pybofractal.png') self.setWindowIcon(QIcon(str(ruta_icono))) self.statusBar().showMessage('Ready') self.show() if __name__ == '__main__': app = QApplication(sys.argv) w = MiVentana() sys.exit(app.exec_())
Barra de menú y menús
Al código anterior le quiero añadir un menu. Si inspeccionamos w
, la instancia de MiVentana
, vemos que tiene lo siguiente:
print(dir(w))
Nos devuelve lo siguiente:
['AllowNestedDocks', 'AllowTabbedDocks', 'AnimatedDocks', 'DockOption', 'DockOptions', 'DrawChildren', 'DrawWindowBackground', 'ForceTabbedDocks', 'GroupedDragging', 'IgnoreMask', 'PaintDeviceMetric', 'PdmDepth', 'PdmDevicePixelRatio', 'PdmDevicePixelRatioScaled', 'PdmDpiX', 'PdmDpiY', 'PdmHeight', 'PdmHeightMM', 'PdmNumColors', 'PdmPhysicalDpiX', 'PdmPhysicalDpiY', 'PdmWidth', 'PdmWidthMM', 'RenderFlag', 'RenderFlags', 'VerticalTabs', '__class__', '__delattr__', '__dict__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattr__', '__getattribute__', '__gt__', '__hash__', '__init__', '__init_subclass__', '__le__', '__lt__', '__module__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', '__weakref__', '_create_menu', '_create_ui', 'acceptDrops', 'accessibleDescription', 'accessibleName', 'actionEvent', 'actions', 'activateWindow', 'addAction', 'addActions', 'addDockWidget', 'addToolBar', 'addToolBarBreak', 'adjustSize', 'autoFillBackground', 'backgroundRole', 'baseSize', 'blockSignals', 'centralWidget', 'changeEvent', 'childAt', 'childEvent', 'children', 'childrenRect', 'childrenRegion', 'clearFocus', 'clearMask', 'close', 'closeEvent', 'colorCount', 'connectNotify', 'contentsMargins', 'contentsRect', 'contextMenuEvent', 'contextMenuPolicy', 'corner', 'create', 'createPopupMenu', 'createWindowContainer', 'cursor', 'customContextMenuRequested', 'customEvent', 'deleteLater', 'depth', 'destroy', 'destroyed', 'devType', 'devicePixelRatio', 'devicePixelRatioF', 'devicePixelRatioFScale', 'disconnect', 'disconnectNotify', 'dockOptions', 'dockWidgetArea', 'documentMode', 'dragEnterEvent', 'dragLeaveEvent', 'dragMoveEvent', 'dropEvent', 'dumpObjectInfo', 'dumpObjectTree', 'dynamicPropertyNames', 'effectiveWinId', 'ensurePolished', 'enterEvent', 'event', 'eventFilter', 'find', 'findChild', 'findChildren', 'focusInEvent', 'focusNextChild', 'focusNextPrevChild', 'focusOutEvent', 'focusPolicy', 'focusPreviousChild', 'focusProxy', 'focusWidget', 'font', 'fontInfo', 'fontMetrics', 'foregroundRole', 'frameGeometry', 'frameSize', 'geometry', 'getContentsMargins', 'grab', 'grabGesture', 'grabKeyboard', 'grabMouse', 'grabShortcut', 'graphicsEffect', 'graphicsProxyWidget', 'hasFocus', 'hasHeightForWidth', 'hasMouseTracking', 'hasTabletTracking', 'height', 'heightForWidth', 'heightMM', 'hide', 'hideEvent', 'iconSize', 'iconSizeChanged', 'inherits', 'initPainter', 'inputMethodEvent', 'inputMethodHints', 'inputMethodQuery', 'insertAction', 'insertActions', 'insertToolBar', 'insertToolBarBreak', 'installEventFilter', 'isActiveWindow', 'isAncestorOf', 'isAnimated', 'isDockNestingEnabled', 'isEnabled', 'isEnabledTo', 'isFullScreen', 'isHidden', 'isLeftToRight', 'isMaximized', 'isMinimized', 'isModal', 'isRightToLeft', 'isSeparator', 'isSignalConnected', 'isVisible', 'isVisibleTo', 'isWidgetType', 'isWindow', 'isWindowModified', 'isWindowType', 'keyPressEvent', 'keyReleaseEvent', 'keyboardGrabber', 'killTimer', 'layout', 'layoutDirection', 'leaveEvent', 'locale', 'logicalDpiX', 'logicalDpiY', 'lower', 'mapFrom', 'mapFromGlobal', 'mapFromParent', 'mapTo', 'mapToGlobal', 'mapToParent', 'mask', 'maximumHeight', 'maximumSize', 'maximumWidth', 'menuBar', 'menuWidget', 'metaObject', 'metric', 'minimumHeight', 'minimumSize', 'minimumSizeHint', 'minimumWidth', 'mouseDoubleClickEvent', 'mouseGrabber', 'mouseMoveEvent', 'mousePressEvent', 'mouseReleaseEvent', 'move', 'moveEvent', 'moveToThread', 'nativeEvent', 'nativeParentWidget', 'nextInFocusChain', 'normalGeometry', 'objectName', 'objectNameChanged', 'overrideWindowFlags', 'overrideWindowState', 'paintEngine', 'paintEvent', 'paintingActive', 'palette', 'parent', 'parentWidget', 'physicalDpiX', 'physicalDpiY', 'pos', 'previousInFocusChain', 'property', 'pyqtConfigure', 'raise_', 'receivers', 'rect', 'releaseKeyboard', 'releaseMouse', 'releaseShortcut', 'removeAction', 'removeDockWidget', 'removeEventFilter', 'removeToolBar', 'removeToolBarBreak', 'render', 'repaint', 'resize', 'resizeDocks', 'resizeEvent', 'restoreDockWidget', 'restoreGeometry', 'restoreState', 'saveGeometry', 'saveState', 'scroll', 'sender', 'senderSignalIndex', 'setAcceptDrops', 'setAccessibleDescription', 'setAccessibleName', 'setAnimated', 'setAttribute', 'setAutoFillBackground', 'setBackgroundRole', 'setBaseSize', 'setCentralWidget', 'setContentsMargins', 'setContextMenuPolicy', 'setCorner', 'setCursor', 'setDisabled', 'setDockNestingEnabled', 'setDockOptions', 'setDocumentMode', 'setEnabled', 'setFixedHeight', 'setFixedSize', 'setFixedWidth', 'setFocus', 'setFocusPolicy', 'setFocusProxy', 'setFont', 'setForegroundRole', 'setGeometry', 'setGraphicsEffect', 'setHidden', 'setIconSize', 'setInputMethodHints', 'setLayout', 'setLayoutDirection', 'setLocale', 'setMask', 'setMaximumHeight', 'setMaximumSize', 'setMaximumWidth', 'setMenuBar', 'setMenuWidget', 'setMinimumHeight', 'setMinimumSize', 'setMinimumWidth', 'setMouseTracking', 'setObjectName', 'setPalette', 'setParent', 'setProperty', 'setShortcutAutoRepeat', 'setShortcutEnabled', 'setSizeIncrement', 'setSizePolicy', 'setStatusBar', 'setStatusTip', 'setStyle', 'setStyleSheet', 'setTabOrder', 'setTabPosition', 'setTabShape', 'setTabletTracking', 'setToolButtonStyle', 'setToolTip', 'setToolTipDuration', 'setUnifiedTitleAndToolBarOnMac', 'setUpdatesEnabled', 'setVisible', 'setWhatsThis', 'setWindowFilePath', 'setWindowFlag', 'setWindowFlags', 'setWindowIcon', 'setWindowIconText', 'setWindowModality', 'setWindowModified', 'setWindowOpacity', 'setWindowRole', 'setWindowState', 'setWindowTitle', 'sharedPainter', 'show', 'showEvent', 'showFullScreen', 'showMaximized', 'showMinimized', 'showNormal', 'signalsBlocked', 'size', 'sizeHint', 'sizeIncrement', 'sizePolicy', 'splitDockWidget', 'stackUnder', 'startTimer', 'staticMetaObject', 'statusBar', 'statusTip', 'style', 'styleSheet', 'tabPosition', 'tabShape', 'tabifiedDockWidgetActivated', 'tabifiedDockWidgets', 'tabifyDockWidget', 'tabletEvent', 'takeCentralWidget', 'testAttribute', 'thread', 'timerEvent', 'toolBarArea', 'toolBarBreak', 'toolButtonStyle', 'toolButtonStyleChanged', 'toolTip', 'toolTipDuration', 'tr', 'underMouse', 'ungrabGesture', 'unifiedTitleAndToolBarOnMac', 'unsetCursor', 'unsetLayoutDirection', 'unsetLocale', 'update', 'updateGeometry', 'updateMicroFocus', 'updatesEnabled', 'visibleRegion', 'whatsThis', 'wheelEvent', 'width', 'widthMM', 'winId', 'window', 'windowFilePath', 'windowFlags', 'windowHandle', 'windowIcon', 'windowIconChanged', 'windowIconText', 'windowIconTextChanged', 'windowModality', 'windowOpacity', 'windowRole', 'windowState', 'windowTitle', 'windowTitleChanged', 'windowType', 'x', 'y']
Los observadores puede que se hayan dado cuenta de la existencia de menuBar
… Como ya comentamos en el capítulo 5 un QMainWindow
no es más que un QWidget
con algunas cosas más. Entre estas cosas ya vimos (en el capítulo 5) que tenía un statusBar
y, vemos ahora, también tiene un menuBar
. Vamos a hacer uso del mismo. Escribo un poco de código nuevo. Cada nueva línea de código se puede identificar porque lleva el comentario ## NUEVA LÍNEA
al final, como hemos venido haciendo hasta ahora:
''' Curso de creación de GUIs con Qt5 y Python Author: Kiko Correoso Website: pybonacci.org Licencia: MIT ''' import os os.environ['QT_API'] = 'pyside2' import sys from pathlib import Path from qtpy.QtWidgets import QApplication, QMainWindow from qtpy.QtGui import QIcon class MiVentana(QMainWindow): def __init__(self): super().__init__() self._create_ui() def _create_ui(self): self.resize(500, 300) self.move(0, 0) self.setWindowTitle('Hola, QMainWindow') ruta_icono = Path('.', 'imgs', 'pybofractal.png') self.setWindowIcon(QIcon(str(ruta_icono))) self.statusBar().showMessage('Ready') self._create_menu() ## NUEVA LÍNEA self.show() def _create_menu(self): ## NUEVA LÍNEA menubar = self.menuBar() ## NUEVA LÍNEA file_menu = menubar.addMenu('&File') ## NUEVA LÍNEA help_menu = menubar.addMenu('&Help') ## NUEVA LÍNEA if __name__ == '__main__': app = QApplication(sys.argv) w = MiVentana() sys.exit(app.exec_())
Podéis guardar el anterior código en un fichero que se llame main00.py o, si habéis descargado el repositorio, podéis usar el que se encuentra en la carpeta apps/07-MenuPrincipal. Lo podéis ejecutar con el terminal en el mismo sitio donde está el programa haciendo (si no os sale el icono es porque no lo tenéis metido en la carpeta apps/07-MenuPrincipal/imgs:
python main00.py
Si todo funciona correctamente deberíais ver una ventana como la siguiente:
En esa ventana se ve que tenemos dos menús, uno llamado File y otro llamado Help. Si pulsáis sobre ellos no pasará nada porque nos falta meter más cosas. Pero antes vamos a comentar el código nuevo.
self._create_menu()
Esta es fácil… Dentro del método _create_ui
llamamos al método _create_menu
. En el segundo es dónde me he dedicado a gestionar la creación del menú.
def _create_menu(self) menubar = self.menuBar() file_menu = menubar.addMenu('&File') help_menu = menubar.addMenu('&Help')
En este método, primero creamos una instancia de QMenuBar
usando el método menuBar
del QMainWindow
y la guardamos en la variable menubar
. En la instancia de QMenuBar
tenemos el método addMenu
que nos permite añadir menús a la barra de menús. El método addMenu
recibe un string. En el string estoy usando un símbolo &
y luego lo que quiero que aparezca en el manú (e.g., '&File'
para que se vea File en el GUI. ¿Para qué sirve el ampersand, “&”? Es una forma rápida y sencilla de navegación. Cuando esté el GUI activo, si pulso sobre la tecla “Alt” hay varias letras del GUI que se verán subrrayadas, en el caso de nuestro GUI serán la F y la H. Si después de pulsar “Alt” pulsamos “F” será una forma de usar el teclado para navegar por nuestro GUI. Este sería un buen momento para experimentar y ejecutar el código cambiando la siguiente linea:
file_menu = menubar.addMenu('&File')
Con
file_menu = menubar.addMenu('File')
o
file_menu = menubar.addMenu('Fil&e')
Si quitamos el ampersand, “&”, perdemos la navegación rápida con teclado para el menú File. Si movemos el ampersand, “&”, a otra letra podremos usar esa otra letra para nuestra navegación rápida con teclado.
Muy bien, ya tenemos un menú pero lo normal es que el menú se despliegue y nos muestre opciones.
Pero antes vamos a hacer un inciso para hablar de qtawesome
.
qtawesome
Todas las aplicaciones quedan más bonitas y usables si usamos iconos bonitos y que nos informen de forma rápida de posibles interacciones que podemos hacer con el GUI. Una forma sencilla de integrar este tipo de iconos es usando la biblioteca qtawesome
desarrollada por el equipo de gente detrás de spyder-ide. Esta biblioteca nos permite integrar de forma sencilla iconos de varios paquetes como FontAwesome, ElusiveIcons o MaterialDesignIcons.
Por tanto, para poder usar qtawesome
antes lo tendréis que instalar en el entorno pyboqt
que venimos usando. Para ello, hacemos lo siguiente en la terminal (o Anaconda Prompt si estás en Windows):
conda activate pyboqt
conda install qtawesome
Para usar un icono de, por ejemplo, FontAwesome podemos hacer lo siguiente:
import qtawesome as qta icono = qta.icon('fa5.times-circle')
Y en icono
ya tendriamos una instancia de QIcon
con el icono times-circle de FontAwesome listo para usarlo en el GUI.
Esto ha sido un vistazo muy rápido a qtawesome
. Para saber más le puedes echar un ojo a la documentación. Para lo que vamos a hacer hoy con lo que he explicado nos vale.
Elementos del menú
Volvemos a los menús…
Para ver cómo añadir elementos a un menú vamos a volver a escribir nuevo código y lo vamos explicando. Y, como siempre, las nuevas líneas vendrán destacadas con el comentario ## NUEVA LÍNEA
:
''' Curso de creación de GUIs con Qt5 y Python Author: Kiko Correoso Website: pybonacci.org Licencia: MIT ''' import os os.environ['QT_API'] = 'pyside2' import sys from pathlib import Path from qtpy.QtWidgets import QApplication, QMainWindow, QAction ## NUEVA LÍNEA from qtpy.QtGui import QIcon import qtawesome as qta ## NUEVA LÍNEA class MiVentana(QMainWindow): def __init__(self): super().__init__() self._create_ui() def _create_ui(self): self.resize(500, 300) self.move(0, 0) self.setWindowTitle('Hola, QMainWindow') ruta_icono = Path('.', 'imgs', 'pybofractal.png') self.setWindowIcon(QIcon(str(ruta_icono))) self.statusBar().showMessage('Ready') self._create_menu() self.show() def _create_menu(self): menubar = self.menuBar() # File menu and its QAction's file_menu = menubar.addMenu('&File') exit_action = QAction(qta.icon('fa5.times-circle'), ## NUEVA LÍNEA '&Exit', ## NUEVA LÍNEA self) ## NUEVA LÍNEA exit_action.setShortcut('Ctrl+Q') ## NUEVA LÍNEA exit_action.setStatusTip('Exit application') ## NUEVA LÍNEA file_menu.addAction(exit_action) ## NUEVA LÍNEA # Help menu and its QAction's help_menu = menubar.addMenu('&Help') about_action = QAction(qta.icon('fa5s.info-circle'), ## NUEVA LÍNEA '&Exit', ## NUEVA LÍNEA self) ## NUEVA LÍNEA about_action.setShortcut('Ctrl+I') ## NUEVA LÍNEA about_action.setStatusTip('About...') ## NUEVA LÍNEA help_menu.addAction(about_action) ## NUEVA LÍNEA if __name__ == '__main__': app = QApplication(sys.argv) w = MiVentana() sys.exit(app.exec_())
Empezamos, de nuevo, a comentar las nuevas líneas:
from qtpy.QtWidgets import QApplication, QMainWindow, QAction ## NUEVA LÍNEA
Añadimos el widget QAction
en el import
. Luego lo explico más en detalle.
import qtawesome as qta ## NUEVA LÍNEA
Esto lo hemos explicado en la sección anterior. importamos la biblioteca qtawesome
para poder integrar fácilmente iconos en nuestra aplicación.
exit_action = QAction(qta.icon('fa5.times-circle'), '&Exit', self) exit_action.setShortcut('Ctrl+Q') exit_action.setStatusTip('Exit application') file_menu.addAction(exit_action)
En el método _create_menu
estábamos creando la barra de menús y habíamos metido dos menús vacios (File y Help). En lás lineas destacadas aquí encima lo que estamos haciendo es crear una “acción” y la metemos en uno de los menús.
Pero, ¿Qué es una acción? En los GUIs hay acciones comunes que se pueden realizar de varias formas. Por ejemplo, para cerrar la aplicación podemos ir al menú “Archivo” y luego pulsar sobre el elemento “Cerrar” (“File” -> “Close” en inglés). Otra forma típica de cerrar es usar “Ctrl+Q”, que suele ser un atajo de teclado para cerrar la aplicación. Una tercera forma sería pulsando sobre el icono cerrar de la barra de herramientas (que todavía no hemos visto). Como todas esas acciones deben tener el mismo resultado se puede usar la clase QAction
para tener una abstracción de ese comportamiento que luego podremos usar en las diferentes formas de cerrar la aplicación.
exit_action = QAction(qta.icon('fa5.times-circle'), '&Exit', self)
: En la primera línea de código es donde se usa la claseQAction
. Para crear una instancia podemos pasar un icono, texto y clase padre o solo texto y la clase padre. En este caso uso la primera forma que incluye un icono. En el icono, en lugar de usarQIcon
y una figura que tengamos en el disco duro hacemos lo mismo pero usandoqtawesome
como he explicado antes. Luego, el texto que queremos que muestre el elemento del menú y, por último, la clase padre será el propioQMainWindow
(comoself
en este caso).exit_action.setShortcut('Ctrl+Q')
: Usamos el métodosetShortcut
deQAction
para añadir un atajo de teclado a la aplicación. En este caso usamosCtrl+Q
como atajo de teclado para que la aplicación se cierre (pero de momento no hará nada).exit_action.setStatusTip('Exit application')
: Con el métodosetStatusTip
añadimos en mensaje que aparecerá en la barra de estado cuando el puntero del ratón esté sobre el elemento del menú.file_menu.addAction(exit_action)
: Por último, anadimos el elemento del menú a su menú usando el métodoaddAction
de la instancia deQMenu
llamadafile_menu
y que hemos creado mediante el métodoaddMenu
deQMenuBar
.
Como podéis ver en la última línea, esto es un poco como un Lego donde tenemos un montón de piezas y las vamos uniendo de alguna forma para obtener, al final, nuestra figura final.
El resto de código del método _create_menu
es repetir lo que acabo de explicar pero para el segundo menú, Help.
Si guardáis el anterior código completo en un fichero que se llame main01.py y lo ejecutáis, al igual que hemos hecho antes, deberéis ver algo parecido a lo siguiente:
En la anterior imagen podemos ver que al pulsar sobre File se despliega su menú. En ese menú podemos ver el icono (el circulito con la X), el texto que le hemos indicado y su atajo de teclado. Al poner el puntero del ratón sobre el elemento Exit vemos que aparece en la barra de estado (status_bar
) el mensaje que habíamos definido, “Exit application”.
Si pulsáis con el botón izquierdo del ratón sobre la opción Exit o si usáis el atajo de teclado “Ctrl+Q” el GUI no hace absolutamente nada. Eso es algo que veremos en el próximo capítulo…
En este capítulo vamos a seguir trabajando nuestro menú,
Añadiendo un submenú
En
un menú podemos añadir acciones o, también, otros menús. Vamos a ver
como. Nuevamente, añadimos primero el código completo resaltando las
líneas nuevas con el comentario ## NUEVA LÍNEA
.
''' Curso de creación de GUIs con Qt5 y Python Author: Kiko Correoso Website: pybonacci.org Licencia: MIT ''' import os os.environ['QT_API'] = 'pyside2' import sys from pathlib import Path from qtpy.QtWidgets import (QApplication, QMainWindow, ## NUEVA LÍNEA QAction, QMenu) ## NUEVA LÍNEA from qtpy.QtGui import QIcon import qtawesome as qta class MiVentana(QMainWindow): def __init__(self): super().__init__() self._create_ui() def _create_ui(self): self.resize(500, 300) self.move(0, 0) self.setWindowTitle('Hola, QMainWindow') ruta_icono = Path('.', 'imgs', 'pybofractal.png') self.setWindowIcon(QIcon(str(ruta_icono))) self.statusBar().showMessage('Ready') self._create_menu() self.show() def _create_menu(self): menubar = self.menuBar() # File menu and its QAction's file_menu = menubar.addMenu('&File') exit_action = QAction(qta.icon('fa5.times-circle'), '&Exit', self) exit_action.setShortcut('Ctrl+Q') exit_action.setStatusTip('Exit application') file_menu.addAction(exit_action) # Help menu and its QAction's help_menu = menubar.addMenu('&Help') about_action = QAction(qta.icon('fa5s.info-circle'), '&Exit', self) about_action.setShortcut('Ctrl+I') about_action.setStatusTip('About...') help_menu.addAction(about_action) # NewMenu menu with a SubMenu and its QAction's new_menu = menubar.addMenu('NewMenu') ## NUEVA LÍNEA new_submenu = QMenu('SubMenu', self) ## NUEVA LÍNEA first_action = QAction('SubMenuAction1', self) ## NUEVA LÍNEA second_action = QAction('SubMenuAction2', self) ## NUEVA LÍNEA new_submenu.addAction(first_action) ## NUEVA LÍNEA new_submenu.addAction(second_action) ## NUEVA LÍNEA new_menu.addMenu(new_submenu) ## NUEVA LÍNEA if __name__ == '__main__': app = QApplication(sys.argv) w = MiVentana() sys.exit(app.exec_())
Podéis guardar el anterior código en un fichero que se llame main02.py o, si habéis descargado el repositorio, podéis usar el que se encuentra en la carpeta apps/07-MenuPrincipal. Lo podéis ejecutar con el terminal en el mismo sitio donde está el programa haciendo (si no os sale el icono es porque no lo tenéis metido en la carpeta apps/07-MenuPrincipal/imgs:
python main02.py
Vemos el resultado:
Y comentamos el nuevo código:
from qtpy.QtWidgets import (QApplication, QMainWindow, ## NUEVA LÍNEA QAction, QMenu) ## NUEVA LÍNEA
Añadimos QMenu
a los widgets que importamos.
new_menu = menubar.addMenu('NewMenu') new_submenu = QMenu('SubMenu', self) first_action = QAction('SubMenuAction1', self) second_action = QAction('SubMenuAction2', self) new_submenu.addAction(first_action) new_submenu.addAction(second_action) new_menu.addMenu(new_submenu)
De nuevo, dentro del método _create_menu
metemos algo más de código para meter un menú dentro de otros menú (submenú). Paso a comentar el código:
new_menu = menubar.addMenu('NewMenu')
: Esto ya lo hemos visto antes. Añadimos un nuevo menú a la barra de menús.new_submenu = QMenu('SubMenu', self)
: Ahora creamos un menú nuevo pero en lugar de usar el métodoaddMenu
del objetoQMenuBar
usamos directamente la claseQMenu
.- Las líneas
first_action = QAction('SubMenuAction1', self)
ysecond_action = QAction('SubMenuAction2', self)
: Son similares a lo visto antes. Simplemente ahora no añadimos atajo de teclado ni mensaje para la barra de estado. - Las líneas
new_submenu.addAction(first_action)' y 'new_submenu.addAction(second_action)
: Esto también lo hemos visto antes. Añadimos ambas acciones al submenú. - Por último,
new_menu.addMenu(new_submenu)
: añade el submenú al menúnew_menu
.
Lo dicho anteriormente, pequeñas piezas de Lego que al montarlas correctamente van adquieriendo forma.
Y, por hoy, creo que ya es suficiente.
Como resumen. Hemos creado menús, submenús, añadido atajos de teclado,… Pero, de momento, no sabemos como interactuar con el GUI, es decir, no nos podemos comunicar con el mismo para que haga cosas. Eso será el objeto del próximo capítulo.
Hola, buenas tardes! Soy nuevo en este mundo de la programacion y estoy con un proyecto de escritorio. Estoy queriendo hacer un sistema, que contiene una ventana princpial con su respectivo menu. Al hacer click en una opcion de la barra de menu, llamo a una ventana (qwidget), hasta ahi todo bien. Pero luego, desde esa ventana abierta, quiero llamar a otra ventana (qwidget), lo cual no estoy logrando hacer funcionar, me podrias comentar si es posible esta operacion y como seria? Muchas gracias.
Es posible. Se puede hacer de varias formas. Si quieres, pregunta por aquí (https://foro.pybonacci.org) y muestra el código que estás intentando y vemos a ver si lo podemos apañar para que te funcione.