1

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

eyllanesc
  • 235,170
  • 19
  • 170
  • 241
tmorgan497
  • 45
  • 4

1 Answers1

0

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()
eyllanesc
  • 235,170
  • 19
  • 170
  • 241
  • Thank you for the assistance! Do you also know how I can handle closing the subwindow using the "X" button, with the ability to reopen it at a later time? If I click the "X" button on one of the subwindows, then re-trigger "fileBarTrig" to reopen the subwindow, I get an error saying "wrapped C/C++ object of type QWidget has been deleted." I've tried using "sw1.setAttribute(Qt.WA_DeleteOnClose, False)" and it works, however the pushbutton controls are also deleted and do not reappear. – tmorgan497 Jun 09 '20 at 21:05