Size of verticalLayout is different in Qt Designer and PyQt program

后端 未结 2 685
挽巷
挽巷 2020-12-07 04:33

In Qt Designer 5.9 the verticalLayout in test.ui had a certain distance to the edge of the window, but after loading test.ui with PyQt

2条回答
  •  难免孤独
    2020-12-07 05:11

    If you check the code of uic.loadUi() you will find the following code:

    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)
    

    The problem is caused by the topIsLayoutWidget() function since the parent will refer to the widget that is used as a base, in this case MainWindow complies with isinstance(parent, QtWidgets.QWidget) and type (parent) not in (QtWidgets.QMainWindow, ...) so topIsLayoutWidget() will return True, so to be left, top, right, bottom be -1 since those properties do not exist will be updated to 0 so the apply to contentsMargins will be established by eliminating the default value (9, 9, 9, 9), but in the case of Qt Designer the contentsMargins have not been updated maintaining their default value.

    So in conclusion is a pyqt bug that also points in the comments:

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

    So there are several solutions:

    • Remove:

      if self.stack.topIsLayoutWidget():
          if left < 0: left = 0
          if top < 0: top = 0
          if right < 0: right = 0
          if bottom < 0: bottom = 0
      
    • Use 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()
      

    I prefer the second solution since the source code should not be modified.

提交回复
热议问题