如何与Python一起正确使用Qt Designer?

问题描述

我正在尝试学习使用Qt Creator和qtpy制作桌面应用程序,但是我的结果看起来不像预期的那样。我在Qt Designer中创建了这个简单的东西(并期望结果看起来类似):

enter image description here

通过保存,我在Python项目目录中的目录'ui'中获得了文件mainwindow.ui。通过运行以下skript一次,我得到了一个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_())

但是结果看起来并不像预期的那样。所有的小部件似乎都太小,其内容已被删减:

enter image description here

如何使结果看起来像Qt Creator?

我在虚拟环境中使用Pycharm社区2020.2 已安装以下Python软件包: PyQt5 v 5.15.0 PyQt5-sip v 12.8.0 qtpy v 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,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
  • 用户自定义

在您的情况下,不一致的原因是Designer使用默认样式 来“绘制”窗口小部件的方式(请注意,您应该能够从“表单”菜单中以不同的样式预览GUI),当您使用 system 默认样式从python实际运行程序时,会发生什么实际情况。

使用布局管理器可以管理和优化可用空间,确保正确显示所有窗口小部件并使用尽可能多或所需的空间。

固定几何有效的情况非常少见,如果您实际上需要它们,那仅仅是因为您真的知道为什么以及如何处理它们。

对于其余99.9%的情况, actual 解决方案是使用布局管理器。
右键单击界面的空白点,打开“布局...”子菜单,然后选择可用的布局之一。如果需要将小部件放置在“特定”位置,请考虑使用网格布局和水平/垂直分隔符(将其从小部件框的顶部拖动)。