使用 pyuic 与 uic.loadUi 的好处
Posted
技术标签:
【中文标题】使用 pyuic 与 uic.loadUi 的好处【英文标题】:Benefits of using pyuic vs uic.loadUi 【发布时间】:2020-04-16 18:56:02 【问题描述】:我目前正在使用 python 和 Qt,这对我来说是来自 C++ 版本的新功能,我意识到在 oficial documentation 中它说可以从 .ui
加载 UI 文件或创建 python类并将文件转换为.py
文件。
我得到了使用.ui
的好处,它是动态加载的,所以不需要在每次更改时将其转换为 python 文件,但是这样做有什么好处?,你在运行时间上有什么改进吗?是别的吗?
谢谢
【问题讨论】:
【参考方案1】:嗯,这个问题很危险地接近“基于意见”的标志,但它也是一个常见的问题,我相信它至少值得部分回答。
从概念上讲,使用pyuic
方法和uic.loadUi()
方法是相同的并且行为方式非常相似,但有一些细微差别。
为了更好地解释这一切,我将使用有关 using Designer 的文档作为参考。
pyuic
方法,或“python 对象”方法
这可能是最流行的方法,尤其是在初学者中。它的作用是创建一个用于创建 ui 的 python 对象,如果按照 “单一继承” 方法使用,它还充当 ui 本身的“接口”,因为其实例创建的ui
对象具有所有可用的小部件作为其属性:如果您创建一个按钮,它将作为ui.pushButton
可用,第一个标签将为ui.label
等等。
在上面链接的文档的第一个示例中,ui
对象是独立的;这是一个非常基本的示例(我相信它只是为了演示其用法,因为除了在 Designer 中创建的连接之外,它不会提供很多交互)并且不是很有用,但它与单继承方法非常相似:按钮将是self.ui.pushButton
,等等。
如果使用“多重继承”方法,ui
对象将与widget子类重合。在这种情况下,按钮将为self.pushButton
,标签为self.label
,等等。
从 python 的角度来看,这非常重要,因为这意味着这些属性名称将覆盖 any 将使用相同名称的其他实例属性:如果您有一个名为“saveFile”的函数并且您将按钮命名为“saveFile”,一旦返回setupUi
,您将不再有任何[直接] 访问该实例方法的权限。在这种情况下,使用单一继承方法可能会有所帮助 - 但实际上,您可以更加注意函数和对象名称。
最后,如果您不知道 pyuic 生成的文件的作用和用途,您可能倾向于使用它来创建程序。出于很多原因,这是错误的,但最重要的是,因为您可能肯定会在某些时候意识到您必须编辑您的 ui,并且将新更改与修改后的代码合并显然是您不想面对的 PITA .
我最近answered 提出了一个相关问题,试图解释更深入地调用setupUi()
时会发生什么。
使用uic.loadUi
我想说这是一种更“模块化”的方法,主要是因为它更直接:正如问题中已经指出的那样,您不必在每次修改 ui 文件时都不断地重新生成它们。
但是,有一个问题。
首先:显然,从 XML 文件加载、解析和构建 UI 不如直接从代码创建 ui 快(这正是 pyuic 文件在 setupUi()
中所做的事情)。
那么,至少有一个关于布局内容边距的相对较小的错误:当使用loadUi
时,默认的系统/表单边距可能会被完全忽略,如果没有明确设置,则设置为 0。有一个解决方法,在Size of verticalLayout is different in Qt Designer and PyQt program 中解释(感谢eyllanesc)。
比较
pyuic
接近
优点:
更快;在一个包含 100 个按钮和一个包含 1200 多个项目的 tablewidget 的非常简单的测试中,我测量了以下最佳结果:
pyuic 加载:33.2ms loadUi 加载:51.8ms由于多种原因,这个比率显然不是线性的,但你可以理解
如果与单继承方式一起使用,可以防止意外的实例属性覆盖,也意味着更“包含”的对象结构 使用 python 导入可确保项目结构更加一致,尤其是在部署过程中(非 python 文件是常见的问题来源) 这些文件的内容实际上具有指导意义,尤其是对初学者而言缺点:
您始终必须记住每次更新 ui 时重新生成 python 文件;我们都知道忘记这样一个看似毫无意义的步骤是多么容易,尤其是在编码数小时之后:我见过很多情况,人们因为无法追踪的问题而在桌子上敲打头(希望是他们两个)几个小时,在意识到他们只是忘记运行 pyuic 或没有在正确的文件上运行它之前;我自己的前额还疼;-) 文件跟踪:您必须为每个 ui 计算 两个 文件,并且您可能会在迁移/forking/etc 的过程中忘记其中一个,如果您忘记了一个 ui 文件,这可能意味着你必须从头开始完全重新创建它 n00b alert:初学者通常会认为生成的python文件是用来创建程序的,这显然是错误的;不幸的是,# WARNING!
消息不够清晰(我几乎一直在向 PyQt 开发人员请求这个问题);虽然这显然不是这种方法的实际问题,但现在它会导致这样
一些 pyuic 生成文件的内容通常是不必要的(最重要的是对象名称,仅用于特定情况),这很明显,因为它是自动生成的(“你可能需要那,安全总比后悔好”);此外,与上述问题相关,人们可能会认为 pyuic 创建的所有内容实际上都是 GUI 所需要的,从而导致不必要的代码降低其可读性
loadUi
方法
优点:
它直接而直接:您在 Designer 上编辑您的 ui,然后保存它(或者,至少,您记得这样做...),当您运行您的代码时,它已经存在;没有大惊小怪,没有混乱,桌子/前额是安全的(r) 文件跟踪和部署:每个 ui 只需一个文件,您可以将所有这些 ui 文件放在一个单独的文件夹中,您无需执行任何其他操作,也不会冒险在途中忘记某些内容李> 直接访问小部件(但这也可以使用多重继承方法来实现)缺点:
上面提到的布局问题 可能的实例属性覆盖并且没有“ui”对象“containment” 加载速度稍慢 路径和部署:加载是使用os
相对路径和系统分隔符完成的,所以如果你将ui放在与加载.ui
的py
文件不同的目录中,你将不得不考虑这一点;此外,一些包管理器用于压缩所有内容,除非正确管理路径,否则会导致访问错误
在我看来,综合考虑,loadUi
方法通常是更好的选择。它不会分散我的注意力,它允许更好的概念划分(这通常很好,并且在概念上更接近于类似于 MVC 的模式)并且我坚信它更不容易出现程序员错误,对于众多原因。
但这显然是一个选择问题。
我们还应该并且永远记住,就像我们所做的所有其他选择一样,使用 ui 文件是一个选项。 有些人完全避免使用它们(就像有些人将它们从字面上用于任何事情一样),但是,就像所有事情一样,这一切并且总是取决于上下文。
【讨论】:
非常感谢您的详细回答。我真的很感激以上是关于使用 pyuic 与 uic.loadUi 的好处的主要内容,如果未能解决你的问题,请参考以下文章