問題描述
在 Qt Designer 5.9 中 test.ui
中的 verticalLayout
與窗口邊緣有一定距離,但在加載 test.ui
在 main.py
中使用 PyQt 5.11.3,verticalLayout
會擴(kuò)展到窗口的邊緣.
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 5.11.3 in main.py
the verticalLayout
extend to the edge of the window.
ma??in.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>
<小時(shí)>
Qt Designer 5.9 中 test.ui
的屏幕截圖:
main.py
加載 test.ui
的截圖:
這種行為的原因是什么?
What's the reason for this behavior?
推薦答案
查看uic.loadUi()
的代碼會發(fā)現(xiàn)如下代碼:
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)
問題是由 topIsLayoutWidget()
函數(shù)引起的,因?yàn)楦讣墝⒁糜米骰A(chǔ)的小部件,在這種情況下 MainWindow 符合 isinstance(parent, QtWidgets.QWidget) 和類型 (parent) not in (QtWidgets.QMainWindow, ...)
所以 topIsLayoutWidget()
將返回 True,所以左、上、右、下為 -1由于這些屬性不存在將被更新為 0,因此將通過消除默認(rèn)值 (9, 9, 9, 9) 來建立對 contentsMargins
的應(yīng)用,但在 Qt Designer 的情況下, contentsMargins
code>contentsMargins 尚未更新,保持其默認(rèn)值.
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.
所以總之是一個(gè) pyqt 錯(cuò)誤,它也在評論中指出:
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.*
所以有幾種解決方案:
刪除:
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()
我更喜歡第二種解決方案,因?yàn)椴粦?yīng)修改源代碼.
I prefer the second solution since the source code should not be modified.
這篇關(guān)于Qt Designer和PyQt程序中verticalLayout的大小不同的文章就介紹到這了,希望我們推薦的答案對大家有所幫助,也希望大家多多支持html5模板網(wǎng)!