使用 pyuic 与 uic.loadUi 的好处
Benefits of using pyuic vs uic.loadUi
我目前正在使用 python 和 Qt,这对我来说是来自 C++ 版本的新事物,我意识到在 oficial documentation 中它说 UI 文件可以从 .ui
或创建 python class 并将文件转换为 .py
文件。
我得到了使用 .ui
的好处,它是动态加载的,所以不需要在每次更改时将其转换为 python 文件,但是这样做有什么好处?,你得到任何运行 时间的改进?还是其他的?
谢谢
好吧,这个问题非常接近 "Opinion-based" 标志,但它也是一个常见问题,我相信它至少值得部分回答。
从概念上讲,使用 pyuic
方法和 uic.loadUi()
方法是相同的,并且行为方式非常相似,但有一些细微差别。
为了更好地解释所有这些,我将使用有关 using Designer 的文档作为参考。
pyuic
方法,或者"python object"方法
这可能是最流行的方法,尤其是在初学者中。它所做的是创建一个用于创建 ui 的 python 对象,如果按照 "single inheritance" 方法使用,它的行为也会作为 ui 本身的 "interface",因为它的实例创建的 ui
对象具有所有可用的小部件作为其属性:如果您创建一个按钮,它将作为 [=14] =], 第一个标签将是 ui.label
等等。
在上面链接的文档的第一个示例中,ui
对象是独立的;这是一个非常基本的例子(我相信给出它只是为了演示它的用法,因为除了在 Designer 中创建的连接之外它不会提供很多交互)并且不是很有用,但它与单一继承方法非常相似:该按钮将是 self.ui.pushButton
,等等
使用IF"multiple inheritance"方法,ui
对象会与widget子类重合。在这种情况下,按钮将是 self.pushButton
,标签将是 self.label
,等等
从 python 的角度来看,这非常重要,因为这意味着那些属性名称将覆盖 任何 其他使用相同名称的实例属性:如果您有一个名为 "saveFile" 的函数,并且您将按钮命名为 "saveFile",那么一旦 setupUi
返回,您将无法再 [直接] 访问该实例方法。在这种情况下,使用单一继承方法可能会有所帮助 - 但实际上,您可以更加注意函数和对象名称。
最后,如果您不知道 pyuic 生成的文件的作用和用途,您可能倾向于使用它来创建您的程序。出于很多原因,这是错误的,但是,最重要的是,因为您肯定会在某个时候意识到您必须编辑 ui,并且将新更改与修改后的代码合并显然是您不知道的 PITA不想面对
我最近 一个相关问题,试图更深入地解释当 setupUi()
被调用时会发生什么。
使用uic.loadUi
我会说这是一种更 "modular" 的方法,主要是因为它更直接:正如问题中已经指出的那样,您不必不断地重新生成 ui每次修改文件。
但是,有一个问题。
首先:显然,从 XML 文件加载、解析和构建 UI 不如直接创建 ui 快来自代码(这正是 pyuic 文件在 setupUi()
中所做的)。
然后,至少有一个关于布局内容边距的相对较小的错误:当使用 loadUi
时,如果未明确设置,默认的 system/form 边距可能会被完全忽略并设置为 0。 (thanks to eyllanesc).
中对此有一个解决方法
比较
pyuic
接近
优点:
速度更快;在一个非常简单的测试中,有一百个按钮和一个包含超过 1200 个项目的 tablewidget,我测量了以下最好的:
- pyuic 加载:33.2ms
- loadUi 加载:51.8 毫秒
由于多种原因,这个比率显然不是线性的,但你可以理解
- 如果和单继承方式一起使用,可以防止意外的实例属性覆盖,也意味着更多的"contained"对象结构
- 使用 python 导入可确保项目结构更加连贯,尤其是在部署过程中(拥有非 python 文件是常见的问题来源)
- 这些文件的内容其实很有指导意义,尤其是对于初学者
缺点:
- 你总是必须记得重新生成python文件每次你更新一个ui;我们都知道忘记这样一个看似毫无意义的步骤是多么容易,特别是在编码数小时之后:我已经看到很多情况,人们因为无法追踪的问题而在桌子上(希望是他们的)敲了几个小时,在意识到他们只是忘记 运行 pyuic 或者没有 运行 它在正确的文件上之前;我自己的额头还在痛 ;-)
- 文件跟踪:您必须为每个 ui 计算 两个 个文件,当 migrating/forking/etc 时,您可能会忘记其中一个,并且如果您忘记了一个 ui 文件,这可能意味着您必须从头开始完全重新创建它
- n00b alert:初学者通常会认为生成的python文件就是用来创建程序的文件,这显然是错误的;不幸的是,
# WARNING!
消息不够清楚(我几乎一直在向 PyQt 开发负责人求助);虽然这显然不是这种方法的实际问题,但现在它的结果是这样
- some 一个pyuic生成文件的内容通常是不需要的(最重要的是对象名,只在特定情况下使用),这很明显,因为它是自动生成的 ("you might need that, so better safe than sorry");此外,与上述问题相关,人们可能会认为 pyuic 创建的所有内容实际上都是 GUI 所需要的,从而导致不必要的代码降低其可读性
loadUi
方法
优点:
- 直接且即时:您在 Designer 上编辑 ui,保存它(或者,至少,您记得这样做...),然后 运行 您的代码它已经在那里了;没有大惊小怪,没有混乱,desks/foreheads 是安全的(r)
- 文件跟踪和部署:每个 ui 只有一个文件,您可以将所有这些 ui 文件放在一个单独的文件夹中,您无需执行任何其他操作,而且您不需要不要冒着在途中忘记东西的风险
- 直接访问小部件(但这也可以使用多重继承方法实现)
缺点:
- 上面提到的布局问题
- 可能的实例属性覆盖并且没有 "ui" 对象 "containment"
- 加载速度稍慢
- 路径和部署:加载是使用
os
相对路径和系统分隔符完成的,因此如果您将 ui 放在与加载该 py
文件不同的目录中=31=] 你得考虑一下;此外,一些包管理器用于压缩所有内容,导致访问错误,除非正确管理路径
在我看来,综合考虑,loadUi
方法通常是更好的选择。它不会分散我的注意力,它允许更好的概念划分(这通常是好的,并且从概念上讲更紧密地遵循类似于 MVC 的模式)而且我坚信它不太容易出现程序员错误,因为很多原因。
但这显然是一个选择问题。
我们还应该并且永远记住,就像我们所做的所有其他选择一样,使用 ui 文件是一个 选项。
有些人完全避免使用它们(因为有些人将它们用于任何事情),但是,就像所有事情一样,这一切 总是 取决于上下文。
我目前正在使用 python 和 Qt,这对我来说是来自 C++ 版本的新事物,我意识到在 oficial documentation 中它说 UI 文件可以从 .ui
或创建 python class 并将文件转换为 .py
文件。
我得到了使用 .ui
的好处,它是动态加载的,所以不需要在每次更改时将其转换为 python 文件,但是这样做有什么好处?,你得到任何运行 时间的改进?还是其他的?
谢谢
好吧,这个问题非常接近 "Opinion-based" 标志,但它也是一个常见问题,我相信它至少值得部分回答。
从概念上讲,使用 pyuic
方法和 uic.loadUi()
方法是相同的,并且行为方式非常相似,但有一些细微差别。
为了更好地解释所有这些,我将使用有关 using Designer 的文档作为参考。
pyuic
方法,或者"python object"方法
这可能是最流行的方法,尤其是在初学者中。它所做的是创建一个用于创建 ui 的 python 对象,如果按照 "single inheritance" 方法使用,它的行为也会作为 ui 本身的 "interface",因为它的实例创建的 ui
对象具有所有可用的小部件作为其属性:如果您创建一个按钮,它将作为 [=14] =], 第一个标签将是 ui.label
等等。
在上面链接的文档的第一个示例中,ui
对象是独立的;这是一个非常基本的例子(我相信给出它只是为了演示它的用法,因为除了在 Designer 中创建的连接之外它不会提供很多交互)并且不是很有用,但它与单一继承方法非常相似:该按钮将是 self.ui.pushButton
,等等
IF"multiple inheritance"方法,ui
对象会与widget子类重合。在这种情况下,按钮将是 self.pushButton
,标签将是 self.label
,等等
从 python 的角度来看,这非常重要,因为这意味着那些属性名称将覆盖 任何 其他使用相同名称的实例属性:如果您有一个名为 "saveFile" 的函数,并且您将按钮命名为 "saveFile",那么一旦 setupUi
返回,您将无法再 [直接] 访问该实例方法。在这种情况下,使用单一继承方法可能会有所帮助 - 但实际上,您可以更加注意函数和对象名称。
最后,如果您不知道 pyuic 生成的文件的作用和用途,您可能倾向于使用它来创建您的程序。出于很多原因,这是错误的,但是,最重要的是,因为您肯定会在某个时候意识到您必须编辑 ui,并且将新更改与修改后的代码合并显然是您不知道的 PITA不想面对
我最近 setupUi()
被调用时会发生什么。
使用uic.loadUi
我会说这是一种更 "modular" 的方法,主要是因为它更直接:正如问题中已经指出的那样,您不必不断地重新生成 ui每次修改文件。
但是,有一个问题。
首先:显然,从 XML 文件加载、解析和构建 UI 不如直接创建 ui 快来自代码(这正是 pyuic 文件在 setupUi()
中所做的)。
然后,至少有一个关于布局内容边距的相对较小的错误:当使用 loadUi
时,如果未明确设置,默认的 system/form 边距可能会被完全忽略并设置为 0。
比较
pyuic
接近
优点:
速度更快;在一个非常简单的测试中,有一百个按钮和一个包含超过 1200 个项目的 tablewidget,我测量了以下最好的:
- pyuic 加载:33.2ms
- loadUi 加载:51.8 毫秒
由于多种原因,这个比率显然不是线性的,但你可以理解
- 如果和单继承方式一起使用,可以防止意外的实例属性覆盖,也意味着更多的"contained"对象结构
- 使用 python 导入可确保项目结构更加连贯,尤其是在部署过程中(拥有非 python 文件是常见的问题来源)
- 这些文件的内容其实很有指导意义,尤其是对于初学者
缺点:
- 你总是必须记得重新生成python文件每次你更新一个ui;我们都知道忘记这样一个看似毫无意义的步骤是多么容易,特别是在编码数小时之后:我已经看到很多情况,人们因为无法追踪的问题而在桌子上(希望是他们的)敲了几个小时,在意识到他们只是忘记 运行 pyuic 或者没有 运行 它在正确的文件上之前;我自己的额头还在痛 ;-)
- 文件跟踪:您必须为每个 ui 计算 两个 个文件,当 migrating/forking/etc 时,您可能会忘记其中一个,并且如果您忘记了一个 ui 文件,这可能意味着您必须从头开始完全重新创建它
- n00b alert:初学者通常会认为生成的python文件就是用来创建程序的文件,这显然是错误的;不幸的是,
# WARNING!
消息不够清楚(我几乎一直在向 PyQt 开发负责人求助);虽然这显然不是这种方法的实际问题,但现在它的结果是这样 - some 一个pyuic生成文件的内容通常是不需要的(最重要的是对象名,只在特定情况下使用),这很明显,因为它是自动生成的 ("you might need that, so better safe than sorry");此外,与上述问题相关,人们可能会认为 pyuic 创建的所有内容实际上都是 GUI 所需要的,从而导致不必要的代码降低其可读性
loadUi
方法
优点:
- 直接且即时:您在 Designer 上编辑 ui,保存它(或者,至少,您记得这样做...),然后 运行 您的代码它已经在那里了;没有大惊小怪,没有混乱,desks/foreheads 是安全的(r)
- 文件跟踪和部署:每个 ui 只有一个文件,您可以将所有这些 ui 文件放在一个单独的文件夹中,您无需执行任何其他操作,而且您不需要不要冒着在途中忘记东西的风险
- 直接访问小部件(但这也可以使用多重继承方法实现)
缺点:
- 上面提到的布局问题
- 可能的实例属性覆盖并且没有 "ui" 对象 "containment"
- 加载速度稍慢
- 路径和部署:加载是使用
os
相对路径和系统分隔符完成的,因此如果您将 ui 放在与加载该py
文件不同的目录中=31=] 你得考虑一下;此外,一些包管理器用于压缩所有内容,导致访问错误,除非正确管理路径
在我看来,综合考虑,loadUi
方法通常是更好的选择。它不会分散我的注意力,它允许更好的概念划分(这通常是好的,并且从概念上讲更紧密地遵循类似于 MVC 的模式)而且我坚信它不太容易出现程序员错误,因为很多原因。
但这显然是一个选择问题。
我们还应该并且永远记住,就像我们所做的所有其他选择一样,使用 ui 文件是一个 选项。
有些人完全避免使用它们(因为有些人将它们用于任何事情),但是,就像所有事情一样,这一切 总是 取决于上下文。