VerticalLayout的尺寸是Qt设计和PyQt的程序不同(Size of verticalL

2019-09-26 05:05发布

在Qt设计5.9 verticalLayouttest.ui不得不窗口的边缘有一定距离,但加载后test.ui与PyQt的5.11.3 main.pyverticalLayout延伸到所述窗口的边缘。

main.py:

    #!/usr/bin/python3
import sys
from PyQt5.QtWidgets import QApplication, QMainWindow
from PyQt5.uic import loadUi

class MainWindow(QMainWindow):
    def __init__(self, parent=None):
        super().__init__()
        loadUi("test.ui", self)

def main():
    app = QApplication(sys.argv)
    main_window = MainWindow(app)
    main_window.show()
    sys.exit(app.exec_())


if __name__ == "__main__":
main()

test.ui:

<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
 <class>MainWindow</class>
 <widget class="QMainWindow" name="MainWindow">
  <property name="geometry">
   <rect>
    <x>0</x>
    <y>0</y>
    <width>350</width>
    <height>257</height>
   </rect>
  </property>
  <property name="windowTitle">
   <string>Test</string>
  </property>
  <widget class="QWidget" name="centralwidget">
   <layout class="QGridLayout" name="gridLayout_2">
    <item row="0" column="0">
     <layout class="QVBoxLayout" name="verticalLayout">
      <property name="leftMargin">
       <number>0</number>
      </property>
      <property name="topMargin">
       <number>0</number>
      </property>
      <item>
       <spacer name="verticalSpacer_2">
        <property name="orientation">
         <enum>Qt::Vertical</enum>
        </property>
        <property name="sizeHint" stdset="0">
         <size>
          <width>20</width>
          <height>40</height>
         </size>
        </property>
       </spacer>
      </item>
      <item>
       <widget class="QGroupBox" name="groupBox">
        <layout class="QGridLayout" name="gridLayout">
         <item row="1" column="1">
          <widget class="QSpinBox" name="spinBox">
           <property name="maximum">
            <number>100000</number>
           </property>
           <property name="value">
            <number>1000</number>
           </property>
          </widget>
         </item>
         <item row="1" column="0">
          <widget class="QLabel" name="label_2">
           <property name="text">
            <string>Test</string>
           </property>
           <property name="alignment">
            <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
           </property>
          </widget>
         </item>
         <item row="0" column="1">
          <widget class="QComboBox" name="comboBox">
           <property name="currentText">
            <string/>
           </property>
          </widget>
         </item>
         <item row="0" column="0">
          <widget class="QLabel" name="label1">
           <property name="text">
            <string>Test</string>
           </property>
           <property name="alignment">
            <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
           </property>
          </widget>
         </item>
        </layout>
       </widget>
      </item>
      <item>
       <spacer name="verticalSpacer">
        <property name="orientation">
         <enum>Qt::Vertical</enum>
        </property>
        <property name="sizeHint" stdset="0">
         <size>
          <width>20</width>
          <height>40</height>
         </size>
        </property>
       </spacer>
      </item>
      <item>
       <widget class="QPushButton" name="pushButton">
        <property name="layoutDirection">
         <enum>Qt::LeftToRight</enum>
        </property>
        <property name="text">
         <string>Test</string>
        </property>
       </widget>
      </item>
     </layout>
    </item>
   </layout>
  </widget>
  <widget class="QMenuBar" name="menubar">
   <property name="geometry">
    <rect>
     <x>0</x>
     <y>0</y>
     <width>350</width>
     <height>28</height>
    </rect>
   </property>
  </widget>
  <widget class="QStatusBar" name="statusbar"/>
 </widget>
 <resources/>
 <connections/>
</ui>

截图test.ui在Qt Designer中5.9:

截图main.py装载test.ui

什么是对这种行为的原因是什么?

Answer 1:

如果你检查的代码uic.loadUi()你会发现下面的代码:

uiparser.py

class UIParser(object):  
    # ...
    def createLayout(self, elem):
        # ...
        margin = -1 if self.stack.topIsLayout() else self.defaults['margin']
        margin = self.wprops.getProperty(elem, 'margin', margin)
        left = self.wprops.getProperty(elem, 'leftMargin', margin)
        top = self.wprops.getProperty(elem, 'topMargin', margin)
        right = self.wprops.getProperty(elem, 'rightMargin', margin)
        bottom = self.wprops.getProperty(elem, 'bottomMargin', margin)
        # A layout widget should, by default, have no margins.
        if self.stack.topIsLayoutWidget():
            if left < 0: left = 0
            if top < 0: top = 0
            if right < 0: right = 0
            if bottom < 0: bottom = 0

    def topIsLayoutWidget(self):
        # A plain QWidget is a layout widget unless it's parent is a
        # QMainWindow or a container widget.  Note that the corresponding uic
        # test is a little more complicated as it involves features not
        # supported by pyuic.

        if type(self[-1]) is not QtWidgets.QWidget:
            return False

        if len(self) < 2:
            return False

        parent = self[-2]

        return isinstance(parent, QtWidgets.QWidget) and type(parent) not in (
                QtWidgets.QMainWindow,
                QtWidgets.QStackedWidget,
                QtWidgets.QToolBox,
                QtWidgets.QTabWidget,
                QtWidgets.QScrollArea,
                QtWidgets.QMdiArea,
                QtWidgets.QWizard,
                QtWidgets.QDockWidget)

该问题是由引起topIsLayoutWidget()函数,因为父将是指被用作基础的微件,在这种情况下主窗口与符合isinstance(parent, QtWidgets.QWidget) and type (parent) not in (QtWidgets.QMainWindow, ...)所以topIsLayoutWidget()将返回True,所以被左,上,右,下是-1,因为不存在将被更新为0的特性,因此适用于contentsMargins将通过消除默认值被确定(9,9,9,9),但在Qt Designer中的情况下, contentsMargins尚未更新保持其默认值。

所以在最后一个PyQt的错误,也指出在评论:

# ... Note that the corresponding uic
# test is a little more complicated as it involves features not
# supported by pyuic.*

因此,有几种解决方案:

  • 去掉:

     if self.stack.topIsLayoutWidget(): if left < 0: left = 0 if top < 0: top = 0 if right < 0: right = 0 if bottom < 0: bottom = 0 
  • 使用uic.loadUiType()

     #!/usr/bin/python3 import sys from PyQt5 import QtCore, QtWidgets, uic Ui_Interface, _ = uic.loadUiType('test.ui') class MainWindow(QtWidgets.QMainWindow, Ui_Interface): def __init__(self, parent=None): super().__init__(parent) self.setupUi(self) def main(): app = QtWidgets.QApplication(sys.argv) main_window = MainWindow() main_window.show() sys.exit(app.exec_()) if __name__ == "__main__": main() 

我更喜欢第二溶液自的源代码不应该被修改。



文章来源: Size of verticalLayout is different in Qt Designer and PyQt program