【问题标题】:How do I dock a subwindow in an MDI Area in pyqt5 using qtDesigner如何使用 qtDesigner 在 pyqt5 的 MDI 区域中停靠子窗口
【发布时间】:2020-09-29 03:10:33
【问题描述】:

我正在尝试在 pyqt5 的 MDI 区域中创建一个子窗口,使用 .ui 文件作为我的主窗口。当我触发显示子窗口的操作时,它显示为一个单独的窗口(未按预期停靠在 MDI 区域中)。我尝试通过本教程 (codeloop.org MDI Area Tutorial) 添加子窗口,它工作正常,但我无法通过加载 .ui 文件来复制它。

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()

主窗口.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 使用非停靠子窗口运行

【问题讨论】:

    标签: python pyqt5 qt-designer qmdiarea


    【解决方案1】:

    似乎是一个bug,或者至少是容量不足,没有在QMdiArea中插入widget,如果分析pyuic5生成的代码就可以看到。

    所以解决办法是把小部件添加到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()
    

    【讨论】:

    • 感谢您的帮助!您还知道如何使用“X”按钮关闭子窗口,并能够在以后重新打开它吗?如果我单击其中一个子窗口上的“X”按钮,然后重新触发“fileBarTrig”以重新打开子窗口,我会收到一条错误消息,提示“已删除 QWidget 类型的包装 C/C++ 对象”。我已经尝试使用“sw1.setAttribute(Qt.WA_DeleteOnClose, False)”并且它可以工作,但是按钮控件也被删除并且不会重新出现。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2018-05-14
    • 1970-01-01
    • 2018-12-06
    • 2019-06-02
    • 1970-01-01
    • 2019-06-17
    • 1970-01-01
    相关资源
    最近更新 更多