I am trying to create a subwindow in an MDI area in pyqt5, using a .ui file for my main window. When I trigger the action to show the subwindow, it shows up as a separate window (not docked in the MDI area as intended). I've tried adding the subwindow via this tutorial (codeloop.org MDI Area Tutorial) and it works fine, but I couldn't replicate it by loading the .ui file.
app.py
import os
import sys
from PyQt5 import QtCore, QtWidgets, uic
scriptPath = os.path.dirname(os.path.realpath(__file__))
uiFile = scriptPath + '\\' + 'mainwindow.ui'
class MainWindow(QtWidgets.QMainWindow):
def __init__(self, *args, **kwargs):
super(MainWindow, self).__init__(*args, **kwargs)
self.initUI()
def initUI(self):
#load the UI page
self.ui_main = uic.loadUi(uiFile, self)
self.action1.triggered.connect(lambda: self.fileBarTrig('test'))
def fileBarTrig(self,p):
print(p)
self.subwindow.show()
self.mdiArea.tileSubWindows()
def main():
app = QtWidgets.QApplication(sys.argv)
main = MainWindow()
main.show()
sys.exit(app.exec_())
if __name__ == '__main__':
main()
mainwindow.ui
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>MainWindow</class>
<widget class="QMainWindow" name="MainWindow">
<property name="windowModality">
<enum>Qt::NonModal</enum>
</property>
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>800</width>
<height>600</height>
</rect>
</property>
<property name="windowTitle">
<string>MainWindow</string>
</property>
<widget class="QWidget" name="centralwidget">
<layout class="QVBoxLayout" name="verticalLayout">
<item alignment="Qt::AlignLeft">
<widget class="QMdiArea" name="mdiArea">
<property name="activationOrder">
<enum>QMdiArea::CreationOrder</enum>
</property>
<property name="viewMode">
<enum>QMdiArea::SubWindowView</enum>
</property>
<property name="documentMode">
<bool>false</bool>
</property>
<widget class="QWidget" name="subwindow">
<property name="windowTitle">
<string>subwindow</string>
</property>
<widget class="QPushButton" name="pushButton">
<property name="geometry">
<rect>
<x>70</x>
<y>80</y>
<width>75</width>
<height>23</height>
</rect>
</property>
<property name="text">
<string>help</string>
</property>
</widget>
</widget>
<widget class="QWidget" name="subwindow_2">
<property name="windowTitle">
<string>Subwindow</string>
</property>
</widget>
</widget>
</item>
</layout>
</widget>
<widget class="QMenuBar" name="menubar">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>800</width>
<height>21</height>
</rect>
</property>
<widget class="QMenu" name="menuFile">
<property name="title">
<string>File</string>
</property>
<addaction name="action1"/>
</widget>
<addaction name="menuFile"/>
</widget>
<widget class="QStatusBar" name="statusbar"/>
<action name="action1">
<property name="text">
<string>1</string>
</property>
</action>
</widget>
<resources/>
<connections/>
</ui>
app.py running with undocked subwindow
It seems that it is a bug, or at least a lack of capacity, that does not insert the widgets in the QMdiArea, that can be seen if the code generated by pyuic5 is analyzed.
So the solution is to add the widgets to the QMdiArea:
import os
import sys
from PyQt5 import QtCore, QtWidgets, uic
scriptPath = os.path.dirname(os.path.realpath(__file__))
uiFile = os.path.join(scriptPath, "mainwindow.ui")
class MainWindow(QtWidgets.QMainWindow):
def __init__(self, *args, **kwargs):
super(MainWindow, self).__init__(*args, **kwargs)
self.initUI()
def initUI(self):
# load the UI page
self.ui_main = uic.loadUi(uiFile, self)
self.action1.triggered.connect(lambda: self.fileBarTrig("test"))
def fileBarTrig(self, p):
sw1 = self.mdiArea.addSubWindow(self.subwindow)
sw1.show()
sw2 = self.mdiArea.addSubWindow(self.subwindow_2)
sw2.show()
self.mdiArea.tileSubWindows()
def main():
app = QtWidgets.QApplication(sys.argv)
main = MainWindow()
main.show()
sys.exit(app.exec_())
if __name__ == "__main__":
main()