创建自定义 Widget 扩展

一旦为Qt Widgets Designer 创建了自定义 widget 插件,就可以使用自定义 widget 扩展为Qt Widgets Designer 工作区提供预期的行为和功能。

扩展类型

Qt Widgets Designer 中有几种可用的扩展类型。您可以以相同的模式使用所有这些扩展,只需替换相应的扩展基类即可。

QDesignerContainerExtension 在实现自定义多页面容器时,扩展类是必要的。

QDesignerTaskMenuExtension

QDesignerTaskMenuExtension 对于自定义 widget 非常有用。它提供了一个扩展,允许您在 Designer 的任务菜单中添加自定义菜单项。Qt Widgets

任务菜单扩展示例说明了如何使用该类。

QDesignerContainerExtension

QDesignerContainerExtension 在实现自定义多页面容器时,该类是必要的。它提供了一个扩展,允许您在 Designer 中为多页面容器插件添加和删除页面。Qt Widgets

容器扩展示例进一步说明了如何使用该类。

注: 由于某些部件(如QTabWidget )的实现方式,无法为其添加自定义的每页属性。

QDesignerMemberSheetExtension

QDesignerMemberSheetExtension 类允许您在连接信号和插槽时操作显示的 widget 成员函数。

QDesignerPropertySheetExtension,QDesignerDynamicPropertySheetExtension

这些扩展类允许您控制 widget 的属性在Qt Widgets Designer 的属性编辑器中的显示方式。

Qt Widgets Designer 使用 和 类为其属性编辑器、信号编辑器和槽编辑器提供数据。每当在工作区中选择一个部件时, Designer 都会查询该部件的属性表扩展;同样,每当请求两个部件之间的连接时, Designer 都会查询部件的成员表扩展。QDesignerPropertySheetExtension QDesignerMemberSheetExtension Qt Widgets Qt Widgets

警告: 所有部件都有默认的属性表和成员表。如果您实现了自定义属性表或成员表扩展,您的自定义扩展将覆盖默认表。

创建扩展

要创建扩展,必须同时继承QObject 和相应的基类,并重新实现其功能。由于我们要实现一个接口,因此必须确保使用扩展类定义中的Q_INTERFACES() 宏将其告知元对象系统。例如

class MyExtension: public QObject,
                   public QdesignerContainerExtension
{
    Q_OBJECT
    Q_INTERFACE(QDesignerContainerExtension)

    ...
}

这样,Qt Widgets Designer 就可以使用qobject_cast() 函数,仅使用QObject 指针来查询支持的接口。

Qt Widgets Designer 公开扩展

Qt Widgets Designer 中,扩展在需要时才会创建。因此,在实现扩展时,您必须子类化QExtensionFactory 以创建一个能够创建扩展实例的类。此外,您还必须向Qt Widgets Designer 的扩展管理器注册您的工厂;扩展管理器会处理扩展的构建。

当有扩展请求时,Qt Widgets Designer 的扩展管理器将遍历其注册的工厂,逐一调用QExtensionFactory::createExtension() 直到找到一个能够为所选部件创建所请求扩展的工厂。然后,该工厂将创建一个扩展实例。

创建扩展工厂

QExtensionFactory 类提供了一个标准扩展工厂,但它也可用作自定义扩展工厂的接口。

创建扩展工厂的目的是重新实现QExtensionFactory::createExtension() 函数,使其能够创建你的扩展,例如MultiPageWidget容器扩展。

您可以创建一个新的QExtensionFactory 并重新实现QExtensionFactory::createExtension() 函数:

QObject *ANewExtensionFactory::createExtension(QObject *object,
        const QString &iid, QObject *parent) const
{
    if (iid != Q_TYPEID(QDesignerContainerExtension))
        return 0;

    if (MyCustomWidget *widget = qobject_cast<MyCustomWidget*>
            (object))
        return new MyContainerExtension(widget, parent);

    return 0;
}

或者使用现有工厂,扩展QExtensionFactory::createExtension() 函数,使工厂也能创建自定义扩展:

QObject *AGeneralExtensionFactory::createExtension(QObject *object,
        const QString &iid, QObject *parent) const
{
    MyCustomWidget *widget = qobject_cast<MyCustomWidget*>(object);

    if (widget && (iid == Q_TYPEID(QDesignerTaskMenuExtension))) {
         return new MyTaskMenuExtension(widget, parent);

    } else if (widget && (iid == Q_TYPEID(QDesignerContainerExtension))) {
        return new MyContainerExtension(widget, parent);

    } else {
        return 0;
    }
}

访问Qt Widgets Designer 的扩展管理器

在实现自定义 widget 插件时,您必须子类化QDesignerCustomWidgetInterface ,以便向Qt Widgets Designer 公开您的插件。Qt Widgets Designer 创建自定义部件"部分将详细介绍这一点。扩展工厂的注册通常在QDesignerCustomWidgetInterface::initialize() 函数中进行:

void MyPlugin::initialize(QDesignerFormEditorInterface *formEditor)
{
    if (initialized)
        return;

    QExtensionManager *manager = formEditor->extensionManager();
    Q_ASSERT(manager != 0);

    manager->registerExtensions(new MyExtensionFactory(manager),
                                Q_TYPEID(QDesignerTaskMenuExtension));

    initialized = true;
}

QDesignerCustomWidgetInterface::initialize() 函数中的formEditor 参数是指向Qt Widgets Designer 当前QDesignerFormEditorInterface 对象的指针。您必须使用QDesignerFormEditorInterface::extensionManager() 函数获取Qt Widgets Designer 扩展管理器的接口。然后使用QExtensionManager::registerExtensions() 函数注册自定义扩展工厂。

有关在Qt Widgets Designer 中创建自定义 widget 扩展的更多信息,请参阅任务菜单扩展容器扩展示例。

© 2025 The Qt Company Ltd. Documentation contributions included herein are the copyrights of their respective owners. The documentation provided herein is licensed under the terms of the GNU Free Documentation License version 1.3 as published by the Free Software Foundation. Qt and respective logos are trademarks of The Qt Company Ltd. in Finland and/or other countries worldwide. All other trademarks are property of their respective owners.