本页描述了使用 Qt Designer 为您的 Qt for Python 项目创建基于 Qt Widgets 的图形界面。 Qt Designer 是一个图形 UI 设计工具,可以作为独立的二进制文件 (pyside6-designer) 使用,也可以嵌入到 Qt Creator IDE 中。使用 Qt Designer 描述了它在 Qt Creator 中的使用。
设计存储在 .ui 文件中,这是一种基于 XML 的格式。 pyside6-uic 工具将在项目构建时将其转换为填充小部件实例的 Python 或 C++ 代码。
要在 Qt Creator 中创建新的 Qt 设计表单,请选择 File/New File Or Project 和“Main Window”作为模板。将其保存为 mainwindow.ui。将 QPushButton 添加到中央小部件的中心。
您的文件 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>400</width>
<height>300</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>110</x>
<y>80</y>
<width>201</width>
<height>81</height>
</rect>
</property>
<property name="text">
<string>PushButton</string>
</property>
</widget>
</widget>
<widget class="QMenuBar" name="menuBar">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>400</width>
<height>20</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>
现在我们准备决定如何使用 Python 中的 UI 文件。
Option A: Generating a Python class
与 UI 文件交互的标准方法是从中生成 Python 类。这要归功于 pyside6-uic 工具。要使用此工具,您需要在控制台上运行以下命令:
pyside6-uic mainwindow.ui > ui_mainwindow.py
我们将命令的所有输出重定向到一个名为 ui_mainwindow.py 的文件,该文件将直接导入:
from ui_mainwindow import Ui_MainWindow
现在要使用它,我们应该为我们的小部件创建一个个性化的类来设置这个生成的设计。
为了理解这个想法,让我们看一下整个代码:
import sys
from PySide6.QtWidgets import QApplication, QMainWindow
from PySide6.QtCore import QFile
from ui_mainwindow import Ui_MainWindow
class MainWindow(QMainWindow):
def __init__(self):
super(MainWindow, self).__init__()
self.ui = Ui_MainWindow()
self.ui.setupUi(self)
if __name__ == "__main__":
app = QApplication(sys.argv)
window = MainWindow()
window.show()
sys.exit(app.exec())
从前面的示例中已经知道 if 语句中的内容,并且我们的新基本类仅包含两个新行,负责从 UI 文件加载生成的 python 类:
self.ui = Ui_MainWindow()
self.ui.setupUi(self)
每次对 UI 文件进行更改时,都必须再次运行 pyside6-uic。
Option B: Loading it directly
要直接加载 UI 文件,我们需要 QtUiTools 模块中的一个类:
from PySide6.QtUiTools import QUiLoader
QUiLoader 让我们可以动态加载 ui 文件并立即使用它:
ui_file = QFile("mainwindow.ui")
ui_file.open(QFile.ReadOnly)
loader = QUiLoader()
window = loader.load(ui_file)
window.show()
此示例的完整代码如下所示:
# File: main.py
import sys
from PySide6.QtUiTools import QUiLoader
from PySide6.QtWidgets import QApplication
from PySide6.QtCore import QFile, QIODevice
if __name__ == "__main__":
app = QApplication(sys.argv)
ui_file_name = "mainwindow.ui"
ui_file = QFile(ui_file_name)
if not ui_file.open(QIODevice.ReadOnly):
print(f"Cannot open {ui_file_name}: {ui_file.errorString()}")
sys.exit(-1)
loader = QUiLoader()
window = loader.load(ui_file)
ui_file.close()
if not window:
print(loader.errorString())
sys.exit(-1)
window.show()
sys.exit(app.exec())
然后要执行它,我们只需要在命令提示符下运行以下命令:
python main.py
QUiLoader 使用 connect() 调用将函数签名作为信号/插槽连接的字符串参数。因此,它无法处理 Python 中的 str 或 list 等 Python 类型,因为这些类型在内部映射到不同的 C++ 类型。
Custom Widgets in Qt Designer
Qt Designer 能够使用用户提供的(自定义)小部件。它们显示在小部件框中,并且可以像 Qt 的小部件一样被拖到表单上(请参阅使用 Qt 设计器使用自定义小部件)。通常,这需要将小部件实现为用 C++ 编写的 Qt Designer 的插件,实现其 QDesignerCustomWidgetInterface 。
Qt for Python 为此提供了一个类似于 registerCustomWidget() 的简单接口。 小部件需要作为 Python 模块提供,如小部件绑定示例(文件 wigglywidget.py)或任务菜单扩展示例(文件 tictactoe.py)所示。 通过提供一个名为 register*.py 的注册脚本并将路径类型的环境变量 PYSIDE_DESIGNER_PLUGINS 指向该目录来向 Qt Designer 注册它。 注册脚本的代码如下所示:
# File: registerwigglywidget.py
from wigglywidget import WigglyWidget
import QtDesigner
TOOLTIP = "A cool wiggly widget (Python)"
DOM_XML = """
<ui language='c++'>
<widget class='WigglyWidget' name='wigglyWidget'>
<property name='geometry'>
<rect>
<x>0</x>
<y>0</y>
<width>400</width>
<height>200</height>
</rect>
</property>
<property name='text'>
<string>Hello, world</string>
</property>
</widget>
</ui>
"""
QPyDesignerCustomWidgetCollection.registerCustomWidget(WigglyWidget, module="wigglywidget",
tool_tip=TOOLTIP, xml=DOM_XML)
QPyDesignerCustomWidgetCollection 提供了 QDesignerCustomWidgetCollectionInterface 的实现,向 Qt Designer 公开自定义小部件,具有用于注册类型或添加 QDesignerCustomWidgetInterface 实例的静态便利功能。 函数 registerCustomWidget() 用于向 Qt Designer 注册一个小部件类型。在简单的情况下,它可以像 QUiLoader.registerCustomWidget() 一样使用。它采用自定义小部件类型和一些可选的关键字参数,传递与 QDesignerCustomWidgetInterface 的 getter 相对应的值:
通过启动器 pyside6-designer 启动 Qt Designer 时,自定义小部件应该在小部件框中可见。
对于高级用法,也可以将类 QDesignerCustomWidgetInterface 的实现而不是类型传递给 addCustomWidget()。这在 taskmenueextension 示例中显示,其中为自定义小部件注册了自定义上下文菜单。该示例是相应的 C++ Task Menu Extension Example 的一个端口。
Troubleshooting the Qt Designer Plugin
必须使用启动器 pyside6-designer。独立的 Qt 设计器不会加载插件。
菜单项帮助/关于插件会弹出一个对话框,显示找到的插件和潜在的加载错误消息。
检查控制台或 Windows 调试视图以获取更多错误消息。
由于 Python 对输出的缓冲,错误消息可能仅在 Qt Designer 终止后出现。
在为 Python 构建 Qt 时,请务必设置 --standalone 选项以正确安装插件。