Python如何正确使用Qt Designer?
How to properly use Qt Designer together with Python?
我正在尝试学习使用 Qt Creator 和 qtpy 制作桌面应用程序,但我的结果看起来不像预期的那样。我在 Qt Designer 中创建了这个简单的东西(并期望结果看起来相似):
通过保存,我在 Python 项目目录的 'ui' 目录中得到了一个文件 mainwindow.ui。通过运行下面的脚本一次,我得到了一个mainwindow.py文件:
from qtpy import uic
uic.compileUiDir("ui")
接下来我运行我的主程序:
import sys
from qtpy import QtWidgets
from ui.mainwindow import Ui_MainWindow
app = QtWidgets.QApplication(sys.argv)
window = QtWidgets.QMainWindow()
ui_window = Ui_MainWindow()
ui_window.setupUi(window)
window.show()
sys.exit(app.exec_())
但是结果并不像预期的那样。所有的Widgets好像都太小了,内容都被砍掉了:
如何使结果看起来像 Qt Creator 中的那样?
我在虚拟环境中使用 Pycharm Community 2020.2
安装了以下 Python 个软件包:
PyQt5 v 5.15.0
PyQt5-sip v 12.8.0
QtPy 1.9.0 版
我使用 Qt Creator 4.11.2
也许提供文件的详细信息会有所帮助
mainwindow.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>398</width>
<height>673</height>
</rect>
</property>
<property name="windowTitle">
<string>MainWindow</string>
</property>
<widget class="QWidget" name="centralWidget">
<widget class="QPushButton" name="pushButton">
<property name="geometry">
<rect>
<x>60</x>
<y>30</y>
<width>113</width>
<height>32</height>
</rect>
</property>
<property name="text">
<string>PushButton</string>
</property>
</widget>
<widget class="QRadioButton" name="radioButton">
<property name="geometry">
<rect>
<x>270</x>
<y>60</y>
<width>100</width>
<height>20</height>
</rect>
</property>
<property name="text">
<string>RadioButton</string>
</property>
</widget>
<widget class="QCheckBox" name="checkBox">
<property name="geometry">
<rect>
<x>50</x>
<y>130</y>
<width>87</width>
<height>20</height>
</rect>
</property>
<property name="text">
<string>CheckBox</string>
</property>
</widget>
</widget>
<widget class="QMenuBar" name="menuBar">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>398</width>
<height>22</height>
</rect>
</property>
</widget>
<widget class="QToolBar" name="mainToolBar">
<attribute name="toolBarArea">
<enum>TopToolBarArea</enum>
</attribute>
<attribute name="toolBarBreak">
<bool>false</bool>
</attribute>
</widget>
<widget class="QStatusBar" name="statusBar"/>
</widget>
<layoutdefault spacing="6" margin="11"/>
<resources/>
<connections/>
</ui>
mainwindow.py:
# -*- coding: utf-8 -*-
# Form implementation generated from reading ui file 'ui\mainwindow.ui'
#
# Created by: PyQt5 UI code generator 5.15.0
#
# WARNING: Any manual changes made to this file will be lost when pyuic5 is
# run again. Do not edit this file unless you know what you are doing.
from PyQt5 import QtCore, QtGui, QtWidgets
class Ui_MainWindow(object):
def setupUi(self, MainWindow):
MainWindow.setObjectName("MainWindow")
MainWindow.resize(398, 249)
self.centralWidget = QtWidgets.QWidget(MainWindow)
self.centralWidget.setObjectName("centralWidget")
self.pushButton = QtWidgets.QPushButton(self.centralWidget)
self.pushButton.setGeometry(QtCore.QRect(60, 30, 113, 32))
self.pushButton.setObjectName("pushButton")
self.radioButton = QtWidgets.QRadioButton(self.centralWidget)
self.radioButton.setGeometry(QtCore.QRect(270, 60, 100, 20))
self.radioButton.setObjectName("radioButton")
self.checkBox = QtWidgets.QCheckBox(self.centralWidget)
self.checkBox.setGeometry(QtCore.QRect(50, 130, 87, 20))
self.checkBox.setObjectName("checkBox")
MainWindow.setCentralWidget(self.centralWidget)
self.menuBar = QtWidgets.QMenuBar(MainWindow)
self.menuBar.setGeometry(QtCore.QRect(0, 0, 398, 21))
self.menuBar.setObjectName("menuBar")
MainWindow.setMenuBar(self.menuBar)
self.mainToolBar = QtWidgets.QToolBar(MainWindow)
self.mainToolBar.setObjectName("mainToolBar")
MainWindow.addToolBar(QtCore.Qt.TopToolBarArea, self.mainToolBar)
self.statusBar = QtWidgets.QStatusBar(MainWindow)
self.statusBar.setObjectName("statusBar")
MainWindow.setStatusBar(self.statusBar)
self.retranslateUi(MainWindow)
QtCore.QMetaObject.connectSlotsByName(MainWindow)
def retranslateUi(self, MainWindow):
_translate = QtCore.QCoreApplication.translate
MainWindow.setWindowTitle(_translate("MainWindow", "MainWindow"))
self.pushButton.setText(_translate("MainWindow", "PushButton"))
self.radioButton.setText(_translate("MainWindow", "RadioButton"))
self.checkBox.setText(_translate("MainWindow", "CheckBox"))
您遇到的问题正是应该始终首选布局管理器的原因,而不是使用固定的几何图形。
您的特定问题的部分解决方案是在所有小部件上使用 adjustSize()
:
ui_window.checkBox.adjustSize()
ui_window.pushButton.adjustSize()
ui_window.radioButton.adjustSize()
通过这种方式,所有小部件都将调整它们的几何形状,确保它们能够显示所有内容。
但是,显然,这不是一个很好的解决方案,这不仅仅是因为您可能有几十个小部件。
固定几何图形的问题在于,您在计算机(甚至 Designer)中看到的内容在不同的计算机上几乎绝不会相同。这可能取决于很多因素,包括:
- 系统配置
- 默认字体和字体大小
- 屏幕分辨率和 DPI
- 用户自定义
在您的情况下,不一致来自设计器如何使用 其 默认样式“绘制”小部件(请注意,您应该能够以不同样式预览您的 GUI,而不是“窗体”菜单)以及当您实际 运行 来自 python 的程序时实际发生的情况,使用 系统 默认样式。
使用布局管理器可以管理和优化可用 space,确保所有小部件都正确显示并尽可能多地使用 space。
固定几何形状有效的情况非常罕见,如果您确实需要它们,那只是因为您确实知道为什么以及如何处理它们。
对于剩下的 99.9% 的情况,实际解决方案是使用布局管理器。
右键单击界面的空白点,打开“布局...”子菜单,然后select其中一种可用布局。如果您需要将小部件放在更“特定”的位置,请考虑使用网格布局和 horizontal/vertical spacers(将它们从小部件框的顶部拖动)。
我正在尝试学习使用 Qt Creator 和 qtpy 制作桌面应用程序,但我的结果看起来不像预期的那样。我在 Qt Designer 中创建了这个简单的东西(并期望结果看起来相似):
通过保存,我在 Python 项目目录的 'ui' 目录中得到了一个文件 mainwindow.ui。通过运行下面的脚本一次,我得到了一个mainwindow.py文件:
from qtpy import uic
uic.compileUiDir("ui")
接下来我运行我的主程序:
import sys
from qtpy import QtWidgets
from ui.mainwindow import Ui_MainWindow
app = QtWidgets.QApplication(sys.argv)
window = QtWidgets.QMainWindow()
ui_window = Ui_MainWindow()
ui_window.setupUi(window)
window.show()
sys.exit(app.exec_())
但是结果并不像预期的那样。所有的Widgets好像都太小了,内容都被砍掉了:
如何使结果看起来像 Qt Creator 中的那样?
我在虚拟环境中使用 Pycharm Community 2020.2 安装了以下 Python 个软件包: PyQt5 v 5.15.0 PyQt5-sip v 12.8.0 QtPy 1.9.0 版 我使用 Qt Creator 4.11.2
也许提供文件的详细信息会有所帮助
mainwindow.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>398</width>
<height>673</height>
</rect>
</property>
<property name="windowTitle">
<string>MainWindow</string>
</property>
<widget class="QWidget" name="centralWidget">
<widget class="QPushButton" name="pushButton">
<property name="geometry">
<rect>
<x>60</x>
<y>30</y>
<width>113</width>
<height>32</height>
</rect>
</property>
<property name="text">
<string>PushButton</string>
</property>
</widget>
<widget class="QRadioButton" name="radioButton">
<property name="geometry">
<rect>
<x>270</x>
<y>60</y>
<width>100</width>
<height>20</height>
</rect>
</property>
<property name="text">
<string>RadioButton</string>
</property>
</widget>
<widget class="QCheckBox" name="checkBox">
<property name="geometry">
<rect>
<x>50</x>
<y>130</y>
<width>87</width>
<height>20</height>
</rect>
</property>
<property name="text">
<string>CheckBox</string>
</property>
</widget>
</widget>
<widget class="QMenuBar" name="menuBar">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>398</width>
<height>22</height>
</rect>
</property>
</widget>
<widget class="QToolBar" name="mainToolBar">
<attribute name="toolBarArea">
<enum>TopToolBarArea</enum>
</attribute>
<attribute name="toolBarBreak">
<bool>false</bool>
</attribute>
</widget>
<widget class="QStatusBar" name="statusBar"/>
</widget>
<layoutdefault spacing="6" margin="11"/>
<resources/>
<connections/>
</ui>
mainwindow.py:
# -*- coding: utf-8 -*-
# Form implementation generated from reading ui file 'ui\mainwindow.ui'
#
# Created by: PyQt5 UI code generator 5.15.0
#
# WARNING: Any manual changes made to this file will be lost when pyuic5 is
# run again. Do not edit this file unless you know what you are doing.
from PyQt5 import QtCore, QtGui, QtWidgets
class Ui_MainWindow(object):
def setupUi(self, MainWindow):
MainWindow.setObjectName("MainWindow")
MainWindow.resize(398, 249)
self.centralWidget = QtWidgets.QWidget(MainWindow)
self.centralWidget.setObjectName("centralWidget")
self.pushButton = QtWidgets.QPushButton(self.centralWidget)
self.pushButton.setGeometry(QtCore.QRect(60, 30, 113, 32))
self.pushButton.setObjectName("pushButton")
self.radioButton = QtWidgets.QRadioButton(self.centralWidget)
self.radioButton.setGeometry(QtCore.QRect(270, 60, 100, 20))
self.radioButton.setObjectName("radioButton")
self.checkBox = QtWidgets.QCheckBox(self.centralWidget)
self.checkBox.setGeometry(QtCore.QRect(50, 130, 87, 20))
self.checkBox.setObjectName("checkBox")
MainWindow.setCentralWidget(self.centralWidget)
self.menuBar = QtWidgets.QMenuBar(MainWindow)
self.menuBar.setGeometry(QtCore.QRect(0, 0, 398, 21))
self.menuBar.setObjectName("menuBar")
MainWindow.setMenuBar(self.menuBar)
self.mainToolBar = QtWidgets.QToolBar(MainWindow)
self.mainToolBar.setObjectName("mainToolBar")
MainWindow.addToolBar(QtCore.Qt.TopToolBarArea, self.mainToolBar)
self.statusBar = QtWidgets.QStatusBar(MainWindow)
self.statusBar.setObjectName("statusBar")
MainWindow.setStatusBar(self.statusBar)
self.retranslateUi(MainWindow)
QtCore.QMetaObject.connectSlotsByName(MainWindow)
def retranslateUi(self, MainWindow):
_translate = QtCore.QCoreApplication.translate
MainWindow.setWindowTitle(_translate("MainWindow", "MainWindow"))
self.pushButton.setText(_translate("MainWindow", "PushButton"))
self.radioButton.setText(_translate("MainWindow", "RadioButton"))
self.checkBox.setText(_translate("MainWindow", "CheckBox"))
您遇到的问题正是应该始终首选布局管理器的原因,而不是使用固定的几何图形。
您的特定问题的部分解决方案是在所有小部件上使用 adjustSize()
:
ui_window.checkBox.adjustSize()
ui_window.pushButton.adjustSize()
ui_window.radioButton.adjustSize()
通过这种方式,所有小部件都将调整它们的几何形状,确保它们能够显示所有内容。
但是,显然,这不是一个很好的解决方案,这不仅仅是因为您可能有几十个小部件。
固定几何图形的问题在于,您在计算机(甚至 Designer)中看到的内容在不同的计算机上几乎绝不会相同。这可能取决于很多因素,包括:
- 系统配置
- 默认字体和字体大小
- 屏幕分辨率和 DPI
- 用户自定义
在您的情况下,不一致来自设计器如何使用 其 默认样式“绘制”小部件(请注意,您应该能够以不同样式预览您的 GUI,而不是“窗体”菜单)以及当您实际 运行 来自 python 的程序时实际发生的情况,使用 系统 默认样式。
使用布局管理器可以管理和优化可用 space,确保所有小部件都正确显示并尽可能多地使用 space。
固定几何形状有效的情况非常罕见,如果您确实需要它们,那只是因为您确实知道为什么以及如何处理它们。
对于剩下的 99.9% 的情况,实际解决方案是使用布局管理器。
右键单击界面的空白点,打开“布局...”子菜单,然后select其中一种可用布局。如果您需要将小部件放在更“特定”的位置,请考虑使用网格布局和 horizontal/vertical spacers(将它们从小部件框的顶部拖动)。