使用 Designer 或 QtCreator 中的 .ui 文件与 QUiLoader 和 pyside6-uic#
本页描述了使用 Qt Widgets Designer 创建图形界面,界面基于 Qt Widgets,用于您的 Qt for Python 项目。_Qt Widgets Designer_ 是一个图形 UI 设计工具,它以独立二进制文件(pyside6-designer
)的形式提供,也可以嵌入到 Qt Creator IDE 中。在 Qt Creator 中的使用请见 使用 Qt Widgets Designer。
设计存储在 .ui
文件中,它是一种基于 XML 的格式。这将由 pyside6-uic 工具在项目构建时转换为 Python 或 C++ 代码,用于填充小部件实例。
在 Qt Creator 中创建新的 Qt 设计表单,选择 File/New File Or Project
并选择“主窗口”作为模板。将其保存为 mainwindow.ui
。将 QPushButton
添加到 centralwidget 的中心。
您的文件 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 文件。
选项 A:生成 Python 类#
与UI文件的标准交互方式是从其中生成一个Python类。这要归功于pyside6-uic
工具。要使用此工具,您需要在控制台中运行以下命令:
pyside6-uic mainwindow.ui -o 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
。
方法B:直接加载直接加载
为了直接加载UI文件,我们需要从QtUiTools模块中获取一个类。
from PySide6.QtUiTools import QUiLoader
QUiLoader
允许我们动态地加载iu文件并立即使用它。
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()
调用。由于这些类型在内部映射到不同的C++类型,因此无法处理Python类型,如str
或list
,因此这些类型无法处理
在Qt小部件设计师中的自定义小部件Qt小部件设计师中的自定义小部件
Qt Widgets Designer能够使用用户提供的(自定义)小部件。它们显示在小部件框中,可以像Qt的小部件一样拖放到表单中(参见使用Qt Widgets Designer的自定义小部件)。通常,这需要在C++中实现,以创建作为插件的小部件并在其上实现QDesignerCustomWidgetInterface。
Qt for Python为此提供了与registerCustomWidget()
相似的简单接口。
如WigglyWidget Example(文件wigglywidget.py
)或Task Menu Extension Example(文件tictactoe.py
)所示,小部件需要以Python模块的形式提供。
将此与Qt Widgets Designer一起注册是通过提供名为register*.py
的注册脚本,并将环境变量PYSIDE_DESIGNER_PLUGINS
的路径类型指向目录来完成的。
注册脚本如下所示:
# 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提供了一个暴露自定义小部件并给Qt Widgets Designer提供静态便利函数来注册类型或在QDesignerCustomWidgetInterface的实例中添加QDesignerCustomWidgetCollectionInterface实现。
函数 registerCustomWidget()
用于将小部件类型注册到 Qt Widgets Designer。在简单的情况下,它可以像这样使用:QUiLoader.registerCustomWidget()
。它接受自定义小部件类型和一些可选的关键字参数,传递值与 QDesignerCustomWidgetInterface 的获取器对应。
通过其启动程序 pyside6-designer
启动 Qt Widgets Designer 时,自定义小部件应在小部件框中可见。
对于高级用法,还可以将 QDesignerCustomWidgetInterface 类的实现在类型传递给 addCustomWidget()
。这可以在 taskmenuextension 示例中看到,在该示例中为自定义小部件注册了自定义上下文菜单。该示例是相应的 C++ 任务菜单扩展示例 的移植。
Qt Widgets Designer 插件故障排除#
必须使用启动程序
pyside6-designer
。独立 Qt Widgets Designer 不会加载插件。菜单项 帮助/关于插件 会弹出一个对话框,显示找到的插件和可能的加载错误消息。
请检查控制台或 Windows 调试视图以获取更多信息错误。
由于 Python 对输出的缓冲,错误消息可能只在小部件已终止后才出现。
在为 Python 构建 Qt 时,请确保将插件的
--standalone
选项设置为正确安装。