PyQT: Can subwindows use their own menubar? If so, how do I implement it

Viewed 234

I am writing a GUI in PyQT5 and am using the MDI for multiple windows. We have a couple of pre-written GUIs (they are well established utilities) that we would like to just use as separate subwindows in an MDI environment. I have figured out how to call the other apps as subwindows, but when the subwindows have focus, the menu bar is that of the main app. That is, the menubar for the subwindow does not show. Oddly enough, when I close my main app, the menu bar of the subwindows lingers.

Here is the main menubar: Main Menubar

Main menubar with actions: Main Menubar Open

Here is what happens when I close the main app; the subwindows' menubar is present (but not really functional) After Main Close

The menubar can be expanded but, it does nothing

Subwindow menubar

Here is sample code of this situation:

#!/usr/bin/env python3
# -*- coding: utf-8 -*-

from PyQt5.QtWidgets import QMainWindow, QApplication, QFileDialog, QTreeView, QMdiSubWindow
from PyQt5.QtGui import QStandardItemModel, QStandardItem, QPalette
from PyQt5 import QtCore
from PyQt5 import QtCore, QtGui, QtWidgets


#  --------------- all of the gui layout class definitions ------------ #


# -----------------------  main MDI app ------------------------#
class Ui_MainWindow(object):
    def setupUi(self, MainWindow):
        MainWindow.setObjectName("MainWindow")
        MainWindow.resize(800, 600)
        self.centralwidget = QtWidgets.QWidget(MainWindow)
        self.centralwidget.setObjectName("centralwidget")
        self.horizontalLayout = QtWidgets.QHBoxLayout(self.centralwidget)
        self.horizontalLayout.setObjectName("horizontalLayout")
        self.mdiArea = QtWidgets.QMdiArea(self.centralwidget)
        self.mdiArea.setObjectName("mdiArea")
        self.horizontalLayout.addWidget(self.mdiArea)
        MainWindow.setCentralWidget(self.centralwidget)
        self.menubar = QtWidgets.QMenuBar(MainWindow)
        self.menubar.setGeometry(QtCore.QRect(0, 0, 800, 22))
        self.menubar.setObjectName("menubar")
        self.menuMenuBar = QtWidgets.QMenu(self.menubar)
        self.menuMenuBar.setObjectName("menuMenuBar")
        MainWindow.setMenuBar(self.menubar)
        self.statusbar = QtWidgets.QStatusBar(MainWindow)
        self.statusbar.setObjectName("statusbar")
        MainWindow.setStatusBar(self.statusbar)
        self.actionApp1 = QtWidgets.QAction(MainWindow)
        self.actionApp1.setObjectName("actionApp1")
        self.actionApp2 = QtWidgets.QAction(MainWindow)
        self.actionApp2.setObjectName("actionApp2")
        self.menuMenuBar.addAction(self.actionApp1)
        self.menuMenuBar.addAction(self.actionApp2)
        self.menubar.addAction(self.menuMenuBar.menuAction())

        self.retranslateUi(MainWindow)
        QtCore.QMetaObject.connectSlotsByName(MainWindow)

    def retranslateUi(self, MainWindow):
        _translate = QtCore.QCoreApplication.translate
        MainWindow.setWindowTitle(_translate("MainWindow", "MainWindow"))
        self.menuMenuBar.setTitle(_translate("MainWindow", "MenuBar"))
        self.actionApp1.setText(_translate("MainWindow", "App1"))
        self.actionApp2.setText(_translate("MainWindow", "App2"))

# -----------------------  app1 app ------------------------#     
class Ui_App1(object):
    def setupUi(self, MainWindow):
        MainWindow.setObjectName("MainWindow")
        MainWindow.resize(800, 600)
        self.centralwidget = QtWidgets.QWidget(MainWindow)
        self.centralwidget.setObjectName("centralwidget")
        MainWindow.setCentralWidget(self.centralwidget)
        self.menubar = QtWidgets.QMenuBar(MainWindow)
        self.menubar.setGeometry(QtCore.QRect(0, 0, 800, 22))
        self.menubar.setObjectName("menubar")
        self.menuApp1MenuBar = QtWidgets.QMenu(self.menubar)
        self.menuApp1MenuBar.setObjectName("menuApp1MenuBar")
        MainWindow.setMenuBar(self.menubar)
        self.statusbar = QtWidgets.QStatusBar(MainWindow)
        self.statusbar.setObjectName("statusbar")
        MainWindow.setStatusBar(self.statusbar)
        self.actionAction1 = QtWidgets.QAction(MainWindow)
        self.actionAction1.setObjectName("actionAction1")
        self.actionAction2 = QtWidgets.QAction(MainWindow)
        self.actionAction2.setObjectName("actionAction2")
        self.menuApp1MenuBar.addAction(self.actionAction1)
        self.menuApp1MenuBar.addAction(self.actionAction2)
        self.menubar.addAction(self.menuApp1MenuBar.menuAction())

        self.retranslateUi(MainWindow)
        QtCore.QMetaObject.connectSlotsByName(MainWindow)

    def retranslateUi(self, MainWindow):
        _translate = QtCore.QCoreApplication.translate
        MainWindow.setWindowTitle(_translate("MainWindow", "MainWindow"))
        self.menuApp1MenuBar.setTitle(_translate("MainWindow", "App1MenuBar"))
        self.actionAction1.setText(_translate("MainWindow", "Action1"))
        self.actionAction2.setText(_translate("MainWindow", "Action2"))


class app1(QMainWindow):

    def __init__(self):
        super().__init__()

        self.ui = Ui_App1()
        self.ui.setupUi(self)

# -----------------------  app2 app ------------------------#      
class Ui_App2(object):
    def setupUi(self, MainWindow):
        MainWindow.setObjectName("MainWindow")
        MainWindow.resize(800, 600)
        self.centralwidget = QtWidgets.QWidget(MainWindow)
        self.centralwidget.setObjectName("centralwidget")
        MainWindow.setCentralWidget(self.centralwidget)
        self.menubar = QtWidgets.QMenuBar(MainWindow)
        self.menubar.setGeometry(QtCore.QRect(0, 0, 800, 22))
        self.menubar.setObjectName("menubar")
        self.menuApp2MenuBar = QtWidgets.QMenu(self.menubar)
        self.menuApp2MenuBar.setObjectName("menuApp2MenuBar")
        MainWindow.setMenuBar(self.menubar)
        self.statusbar = QtWidgets.QStatusBar(MainWindow)
        self.statusbar.setObjectName("statusbar")
        MainWindow.setStatusBar(self.statusbar)
        self.actionAction1 = QtWidgets.QAction(MainWindow)
        self.actionAction1.setObjectName("actionAction1")
        self.actionAction2 = QtWidgets.QAction(MainWindow)
        self.actionAction2.setObjectName("actionAction2")
        self.menuApp2MenuBar.addAction(self.actionAction1)
        self.menuApp2MenuBar.addAction(self.actionAction2)
        self.menubar.addAction(self.menuApp2MenuBar.menuAction())

        self.retranslateUi(MainWindow)
        QtCore.QMetaObject.connectSlotsByName(MainWindow)

    def retranslateUi(self, MainWindow):
        _translate = QtCore.QCoreApplication.translate
        MainWindow.setWindowTitle(_translate("MainWindow", "MainWindow"))
        self.menuApp2MenuBar.setTitle(_translate("MainWindow", "App2MenuBar"))
        self.actionAction1.setText(_translate("MainWindow", "Action1"))
        self.actionAction2.setText(_translate("MainWindow", "Action2"))


class app2(QMainWindow):

    def __init__(self):
        super().__init__()

        self.ui = Ui_App2()
        self.ui.setupUi(self)      


# ----------  subclass the subwindow to catch the close events ---------- #
class QMdiSubWindowMod(QMdiSubWindow):
    def __init__(self):
        super().__init__()
        self.forceClose = False

    def closeEvent(self, event):
        if(self.forceClose):
            event.accept()
        else:
            event.ignore()
            self.hide()    


# ------------------------- MainWindow ------------------------- #

class mainGui(QMainWindow):

    def __init__(self):
        super().__init__()

        self.ui = Ui_MainWindow()
        self.ui.setupUi(self)

        # call and open the subwindows are QMainWindows with menubars
        # ------------ Sub Windows ------
        self.subWinApp1 = QMdiSubWindowMod()
        self.subWinApp1.setWidget(app1())
        self.subWinApp1.setWindowTitle('App1')
        self.ui.mdiArea.addSubWindow(self.subWinApp1)
        self.subWinApp1.hide()

        self.subWinApp2 = QMdiSubWindowMod()
        self.subWinApp2.setWidget(app2())
        self.subWinApp2.setWindowTitle('App2')
        self.ui.mdiArea.addSubWindow(self.subWinApp2)
        self.subWinApp2.hide()

        # set up all the event handlers
        self.setConnections()

    def setConnections(self):
        self.ui.actionApp1.triggered.connect(self.openApp1)
        self.ui.actionApp2.triggered.connect(self.openApp2)

    def closeEvent(self, event):
        self.subWinApp1.forceClose = True
        self.subWinApp1.close()

        self.subWinApp2.forceClose = True
        self.subWinApp2.close()

        event.accept()

    def openApp1(self):
        self.subWinApp1.show()
        self.subWinApp1.setFocus()

    def openApp2(self):
        self.subWinApp2.show()
        self.subWinApp2.setFocus()

def openWin():
    if not QtWidgets.QApplication.instance():
        app = QtWidgets.QApplication(sys.argv)
    else:
        app = QtWidgets.QApplication.instance()
    win = mainGui()
    win.show()

    return win


if __name__ == '__main__':         
    m = openWin()
0 Answers
Related