使用 pyuic 与 uic.loadUi 的优点

Jua*_*njo 3 qt pyqt qt-designer pyuic pyside2

我目前正在使用 python 和 Qt,这对来自 C++ 版本的我来说是新的,我意识到在官方文档中它说 UI 文件可以从 python 类加载.ui或创建 python 类并将文件转换为.py文件。

我得到了使用它的好处,.ui它是动态加载的,因此不需要每次更改时都将其转换为 python 文件,但是这样做有什么好处?,运行时有任何改进吗?难道是别的什么?

谢谢

mus*_*nte 6

好吧,这个问题非常接近“基于意见”的旗帜,但它也是一个常见问题,我相信它至少值得得到部分答案。

从概念上讲,使用pyuic方法和uic.loadUi()方法是相同的,并且行为方式非常相似,但有一些细微的差异。为了更好地解释这一切,我将使用有关使用 Designer 的
文档作为参考。

pyuic方法,或“python 对象”方法

这可能是最流行的方法,尤其是对于初学者来说。它的作用是创建一个用于创建 ui 的 python 对象,如果按照“单继承”方法使用,它也充当 ui 本身的“接口”,因为ui它的实例创建的对象具有所有小部件可用作为其属性:如果您创建一个按钮,它将可用为ui.pushButton,第一个标签将为ui.label等等。

在上面链接的文档的第一个示例中,该ui对象是独立的;这是一个非常基本的示例(我相信给出它只是为了演示其用法,因为除了在 Designer 中创建的连接之外,它不会提供大量交互)并且不是很有用,但它与单一继承方法非常相似:按钮将是self.ui.pushButton等等。

如果使用“多重继承”方法,该ui对象将与小部件子类一致。在这种情况下,按钮将是self.pushButton、标签self.label等。

从 python 的角度来看,这非常重要,因为这意味着这些属性名称将覆盖使用相同名称的任何其他实例属性:如果您有一个名为“saveFile”的函数并且将按钮命名为“saveFile”,那么setupUi一旦返回,将不再有对该实例方法的任何[直接]访问。在这种情况下,使用单一继承方法可能会有所帮助 - 但实际上,您可以更加小心函数和对象名称。

最后,如果您不知道 pyuic 生成的文件的作用和用途,您可能倾向于使用它来创建程序。出于很多原因,这是错误的,但最重要的是,因为您可能肯定会在某些时候意识到必须编辑 ui,并且将新更改与修改后的代码合并显然是您不想面对的 PI​​TA 。

我最近回答了一个相关问题,试图setupUi()更深入地解释调用时会发生什么。

使用uic.loadUi

我想说这是一种更“模块化”的方法,主要是因为它更直接:正如问题中已经指出的那样,您不必在每次修改 ui 文件时不断地重新生成它们。

但是,有一个问题。

首先:显然,从 XML 文件加载、解析和构建 UI 不如直接从代码创建 ui 快(这正是 pyuic 文件在 中所做的事情setupUi())。

然后,关于布局内容边距至少存在一个相对较小的错误:当使用 时loadUi,如果未显式设置,默认的系统/表单边距可能会被完全忽略并设置为 0。有一个解决方法,在 Qt Designer 和 PyQt 程序中的 VerticalLayout 大小不同中进行了解释(感谢eyllanesc)。


一个对比

pyuic方法

优点:

  • 它更快;在一个非常简单的测试中,我使用了 100 个按钮和一个包含 1200 多个项目的表格小部件,测量了以下最佳结果:

    • pyuic加载:33.2ms
    • loadUi加载:51.8ms

    由于多种原因,这个比率显然不是线性的,但你可以明白这个想法

  • 如果与单继承方法一起使用,可以防止意外的实例属性覆盖,同时也意味着更加“包含”的对象结构
  • 使用 python 导入可确保项目结构更加连贯,尤其是在部署过程中(具有非 python 文件是常见的问题来源)
  • 这些文件的内容实际上很有指导意义,特别是对于初学者

缺点:

  • 每次更新 ui时,必须记住重新生成 python 文件;我们都知道,忘记这样一个看似毫无意义的步骤是多么容易,尤其是在编码几个小时之后:我见过很多情况,人们因为无法追踪的问题而在桌子上敲头(希望是他们的)几个小时,在意识到他们只是忘记运行 pyuic 或没有在正确的文件上运行它之前;我自己的额头仍然很痛;-)
  • 文件跟踪:您必须为每个 ui 计算两个文件,并且在迁移/分叉等过程中您可能会忘记其中一个文件,如果您忘记了一个 ui 文件,则可能意味着您必须从头开始完全重新创建它
  • n00b警告:初学者通常会认为生成的python文件就是用来创建他们的程序的文件,这显然是错误的;不幸的是,这个# WARNING!消息还不够清楚(我几乎一直在向 PyQt 的首席开发人员乞讨这一点);虽然这显然不是这种方法的实际问题,但现在它的结果是这样
  • pyuic 生成的文件的某些内容通常是不必要的(最重要的是对象名称,仅用于特定情况),这是非常明显的,因为它是自动生成的(“你可能需要它,所以安全总比抱歉好” ”);另外,与上述问题相关,人们可能会认为 pyuic 创建的所有内容实际上都是 GUI 所需要的,从而导致不必要的代码,从而降低了其可读性

loadUi方法

优点:

  • 它是直接且立即的:您在 Designer 上编辑您的 ui,保存它(或者,至少,您记得这样做......),并且当您运行代码时它已经在那里;没有大惊小怪,没有混乱,桌子/额头很安全(r)
  • 文件跟踪和部署:每个 ui 只有一个文件,您可以将所有这些 ui 文件放在一个单独的文件夹中,您无需执行任何其他操作,也不会冒忘记某些内容的风险
  • 直接访问小部件(但这也可以使用多重继承方法来实现)

缺点:

  • 上面提到的布局问题
  • 可能的实例属性覆盖并且没有“ui”对象“包含”
  • 加载速度稍慢
  • 路径和部署:加载是使用os相对路径和系统分隔符完成的,因此,如果将 ui 放在与py加载的文件不同的目录中,则.ui必须考虑这一点;此外,一些包管理器使用压缩所有内容,导致访问错误,除非路径得到正确管理

我认为,综合考虑,该loadUi方法通常是更好的选择。它不会分散我的注意力,它允许更好的概念划分(这通常很好,并且从概念上讲也更紧密地遵循类似于 MVC 的模式),并且我坚信它对于许多人来说不太容易出现程序员错误。原因。

但这显然是一个选择问题。

我们还应该永远记住,就像我们所做的所有其他选择一样,使用 ui 文件是一种选择
有些人完全避免使用它们(因为有些人确实将它们用于任何事情),但是,就像所有事情一样,这一切都始终取决于上下文。