在 Python 中子类化小部件以与 Qt Designer 一起使用的最简单方法

2023-12-03

我正在使用 PyQt5 构建一个应用程序,(大部分)GUI 是使用 Qt Designer 构建的。我有一些 UI 元素基本上做同样的事情,将它们的代码移动到从基类继承的类中(而基类又从 QTableWidget 继承)似乎是明智的。

这看起来非常简单,只是我不确定如何让 Qt Designer 在生成 UI 文件时使用这些类。我找到了在 PyQt4 中执行此操作的指南 and 另一种适用于 Qt 5,但使用本机 C++ 代码 and 还有一个这是针对 PyQt5 的,但不涉及使子类在 Qt Designer 中可用的(最复杂的)方面。

如何使使用 PyQt5 创建的小部件的子类可在 Qt Designer 中使用?

或者,有没有更简单的方法来做到这一点?我不需要更改小部件的外观或功能 - 我主要只是寻找一个有组织的位置来存储一些代码,使数据更易于设置和访问。


虽然可以为 Qt Designer 创建插件,但not一个简单的任务:官方文档已经过时,有时不完整,并且某些功能尚未完全移植以实现透明的 PyQt 使用。

The easiest方法是使用推广的小部件.

假设您有一个以一种奇特的方式显示当前时间的小部件:

from PyQt5 import QtCore, QtGui, QtWidgets, uic

class TimeFrame(QtWidgets.QFrame):
    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self.updateTimer = QtCore.QTimer(interval=60000, timeout=self.update)
        self._time = None

    @QtCore.pyqtProperty(QtCore.QTime)
    def time(self):
        return self._time

    @time.setter
    def time(self, time):
        self._time = time
        self.update()

    def paintEvent(self, event):
        super().paintEvent(event)
        size = min(self.width(), self.height()) - 10
        rect = QtCore.QRect(0, 0, size, size)
        rect.moveCenter(self.rect().center())
        qp = QtGui.QPainter(self)
        qp.setRenderHints(qp.Antialiasing)
        qp.drawEllipse(rect)
        qp.setPen(QtCore.Qt.NoPen)
        qp.setBrush(QtCore.Qt.blue)
        time = self._time or QtCore.QTime.currentTime()
        minuteAngle = time.minute() * 6
        qp.drawPie(rect, 1440, -minuteAngle * 16)
        qp.setBrush(QtCore.Qt.red)
        hourAngle = (time.hour() % 12 + time.minute() / 60) * 30
        qp.drawPie(rect.adjusted(30, 30, -30, -30), 1440, -hourAngle * 16)

这是一个简单的时钟小部件,显示一对“馅饼”,较大的表示分钟,较小的表示小时(在此屏幕截图中,时间为 2:03):

fancy clock widget


现在,为了能够从设计器添加该小部件,您需要promote一个小部件。推广小部件是 Qt 扩展添加到 UI 的小部件的特性和功能的一种方式。
这非常有用,因为您可以扩展any以您自己的方式标准小部件类:例如,如果您将 QTableView 添加到 UI 并提升它,它允许您从 Designer 界面设置标准 QTableView 属性,然后从代码中实现其他功能。

一旦您知道它是如何工作的,该过程就非常简单。

  1. 创建 UI 并根据要扩展的类添加小部件

在本例中,我使用 QFrame 来展示如何扩展该类属性。 只需创建您的界面,然后将 QFrame 添加到布局中即可。

basic GUI

正如您所看到的,从对象检查器报告的类仍然是 QFrame。

  1. 推广小部件

右键单击要用于课堂的小部件,然后选择Promote to...,然后将“Promoted class name”设置为之前创建的widget类名,并将“头文件”设置为模块名称包含该类。我将 python 文件保存为promoted.py,所以字段值将是promoted。请考虑头文件路径相对于加载 UI 文件的路径。

promote widget in Designer

然后点击“添加”创建新推广的小部件“类”,最后点击“推广”正式推广它。之后,您可以将任何小部件提升为先前设置的提升类,只要基类兼容:如果您的界面中有另一个QFrame,您可以右键单击它并从“提升到”中选择提升的类子菜单。

现在对象检查器中显示的类是TimeFrame.

The object class has changed

  1. 设置对象属性,保存,创建代码并运行

由于我们使用的是 QFrame,因此我们可以设置它的框架(这是因为我们还在paintEvent(event)之前的方法)。

Watch, a raised frame!

现在您只需实现主小部件的基类即可。请记住,每次加载升级的小部件时,都会加载其“头文件”,这意味着其代码将always被运行。这就是为什么重要的是if __name__ == '__main__':只要代码块包含主“程序”和升级的小部件类,就会将代码块放置在文件中。

promoted.py code:

class Test(QtWidgets.QWidget):
    def __init__(self):
        super().__init__()
        uic.loadUi('test.ui', self)

        self.timeEdit.timeChanged.connect(self.updateTimeFrame)

        self.timeEdit.setTime(QtCore.QTime.currentTime())

    def updateTimeFrame(self):
        self.timeFrame.time = self.timeEdit.time()


if __name__ == '__main__':
    import sys
    app = QtWidgets.QApplication(sys.argv)
    w = Test()
    w.show()
    sys.exit(app.exec())

现在,显然 Designer 中不会显示任何内容,but一旦我们运行代码,升级的小部件就会按预期显示!

The promoted widget at work! Cool!

And now you can also know the actual time it took me to create this answer, cool ;-)

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

在 Python 中子类化小部件以与 Qt Designer 一起使用的最简单方法 的相关文章

随机推荐

  • 访问新窗口 - cypress.io

    问题就这么简单 在 Cypress 中 如何访问运行测试时打开的新窗口 重新创建的步骤 运行测试 进行一些操作后 会弹出新窗口 URL 本质上是动态的 填写新窗口中的字段 然后单击几个按钮 在新窗口中完成所需操作后 关闭新窗口并返回主窗口
  • 如何重写动态对象属性的 get 访问器

    假设我有以下课程 public class Person public string Name get set public string Surname get set public string FullName get return
  • 滚动滞后差异

    好的 我希望在 R 中创建滚动滞后差异 vec lt c 43 79979 44 04865 44 17308 44 54638 44 79524 44 79524 44 79524 44 42195 44 54638 44 79524 4
  • 初始化本地安装的 ESLint 后节点模块消失

    在我最初的反应应用程序中 由react native init project name 在我的项目文件夹中 我通过以下方式在本地安装 ESLintyarn add eslint dev 然后我通过以下方式初始化我的配置 node modu
  • 每日本地通知不起作用

    我的问题是我正在尝试安排每天在特定时间发出的通知 这是我的代码 import SwiftUI struct notifView View var body some View VStack VStack Button Request Per
  • 使用jquery改变li的背景颜色

    我想改变当鼠标经过它时包含锚点的 li 的颜色 我这样做 ul li class sonItem a href son 1 a li li class sonItem a href son 2 a li ul 而 jquery 是 docu
  • 如何在 bash 中一遍又一遍地运行命令直到成功?

    我有一个脚本 想向用户询问一些信息 但在用户填写此信息之前 脚本无法继续 以下是我尝试将命令放入循环中以实现此目的 但由于某种原因它不起作用 echo Please change password while passwd do echo
  • 数组中出现次数最多的元素 (bash 3.2)

    在使用 bash 的 shell 脚本中 我想找到数组中最常出现的数字并将结果存储在变量 result 中 该数组可以有任意数量的值 如果返回多个结果 那么我想选择最小的数字 我知道 bash 可能不是最好的工具 并且我愿意接受在 Mac
  • PHP 的 filter_var FILTER_VALIDATE_EMAIL 真的有效吗?

    在阅读了各种帖子后 我决定不使用 REGEX 来检查电子邮件是否有效 而是简单地使用 PHP 内置的 filter var 函数 它似乎工作正常 直到它开始告诉我一封电子邮件无效 因为我里面有一个号码 ie 电子邮件受保护 有效 同时 电子
  • 如何强制在 Visual Studio 2013 中打开解决方案文件 (SLN)?

    尝试在 VS 2013 中显式打开 VS 2012 解决方案 SLN 文件 会成功 只需在 Windows 资源管理器中双击它 仍然会在 VS 2012 中打开它 我读了 Visual Studio 2012 无法转换 vs2010 解决方
  • 遍历 XML 文件中的所有节点

    我想遍历 XML 文件中的所有节点并打印它们的名称 做这个的最好方式是什么 我正在使用 NET 2 0 您可以使用Xml文档 一些 XPath 也很有用 只是一个简单的例子 XmlDocument doc new XmlDocument d
  • 创建一个映射来调用 Spark Dataframe 的每一行的 POJO

    我在 R 中构建了一个 H2O 模型并保存了 POJO 代码 我想使用 POJO 在 hdfs 中对 parquet 文件进行评分 但我不知道如何去做 我计划将 parquet 文件读入 Spark scala SparkR PySpark
  • 在java中编写unicode(Sindhi)的keyListener的实现问题

    我想通过实现 keyListener 来使用 unicodejTextField这样 textField addKeyListener new KeyListener Override public void keyTyped KeyEve
  • 如何以编程方式获取在 UWP 应用清单中启用的所有功能

    我想要创建一个库 并且需要以编程方式检查使用我的库的 UWP 应用程序中启用了哪些功能 怎么做 直接将 appxmanifest 作为 XML 文件读取是此处的方法 像这样的东西 var doc XDocument Load AppxMan
  • Jenkins - 一个版本有多少个 CI/CD 管道?

    对于任何版本 使用下面的 Git 工作流程 对于持续交付 我的理解是 需要创建两条Jenkins管道 如下所示 1 构建在每个合并时触发的管道Feature分支 绿色 进入Develop分支 紫色 管道将推product x y snaps
  • Swift NSDate ISO 8601 格式

    我正在 Swift 中处理日期格式 并尝试将字符串日期转换为 NSDate 将 NSSate 转换为字符串日期 ISO 8601 格式 这是我的代码 let stringDate 2016 05 14T09 30 00 000Z ISO 8
  • Android:相机模式打开时返回按钮不起作用

    在我的应用程序中 有一个照片按钮 当我单击该按钮时 应用程序以相机模式打开 并且在捕获照片后 它将返回到布局上并显示在此布局上捕获的照片 但是当应用程序处于相机模式并且当我按下返回按钮时 应用程序将停止工作它显示 应用程序 AppName
  • java中如何查找一个字符串对象重复了多少次?

    我必须字符串对象 String first Some object that has a loop in it object String second object 我需要做的是找出第二个对象在第一个对象中重复了多少次 你能告诉我该怎么做
  • 当用户单击网页上的链接时,打开 Google 地球并加载特定的 KML 文件

    我目前正在开发一个网站 该网站在 Google 地图中显示地图数据 但也有一个在 Google 地球中显示地图数据的链接 要在 Google 地球中查看此数据 用户单击链接 下载文件 然后使用 Google 地球打开该文件 有没有一种方法可
  • 在 Python 中子类化小部件以与 Qt Designer 一起使用的最简单方法

    我正在使用 PyQt5 构建一个应用程序 大部分 GUI 是使用 Qt Designer 构建的 我有一些 UI 元素基本上做同样的事情 将它们的代码移动到从基类继承的类中 而基类又从 QTableWidget 继承 似乎是明智的 这看起来