本文主要阐述的是自定义控件插件的创建与调用方法和注意事项点。
目录
一、创建自定义控件插件
1、Qt Designer专用接口
基类:QDesignerCustomWidgetCollectionInterface
用途:将所有自定义控件类装载到一个QList里面
#pragma once
#include <QtDesigner>
#include <qplugin.h>
class WidgetCollectionInterface : public QObject, public QDesignerCustomWidgetCollectionInterface
{
Q_OBJECT
Q_INTERFACES(QDesignerCustomWidgetCollectionInterface)
#if QT_VERSION >= 0x050000
Q_PLUGIN_METADATA(IID "org.qt-project.Qt.QDesignerCustomWidgetCollectionInterface")
#endif // QT_VERSION >= 0x050000
public:
WidgetCollectionInterface(QObject* parent = 0);
QList<QDesignerCustomWidgetInterface*> customWidgets() const override;
private:
QList<QDesignerCustomWidgetInterface*> widgets;
};
关键点:
两个宏,声明唯一接口
Q_INTERFACES(QDesignerCustomWidgetCollectionInterface)
Q_PLUGIN_METADATA(IID "org.qt-project.Qt.QDesignerCustomWidgetCollectionInterface")
构造函数中装载所有自定义控件类
WidgetCollectionInterface::WidgetCollectionInterface(QObject* parent)
: QObject(parent)
{
widgets.append(new MyProgressBar1Interface(this));
//widgets.append(new CustomWidgetTwoInterface(this));
//widgets.append(new CustomWidgetThreeInterface(this));
}
1.2、单个自定义控件接口
基类:QDesignerCustomWidgetInterface
用途:通过重写虚函数完成单个自定义控件信息的定义,使得Qt Designer可以通过dll动态调用方式加载到自定义控件的信息,
其信息包括控件图标、控件名字、控件头文件、控件所在组名、控件类名、Qt Designer拖拽自动生成的对象实例默认名称等
#pragma once
#include <QtUiPlugin/QDesignerCustomWidgetInterface>
#include <QtDesigner/QtDesigner>
class MyProgressBar1Interface : public QObject, public QDesignerCustomWidgetInterface
{
Q_OBJECT
Q_INTERFACES(QDesignerCustomWidgetInterface)
public:
MyProgressBar1Interface(QObject *parent = Q_NULLPTR);
bool isContainer() const;
bool isInitialized() const;
QIcon icon() const;
QString domXml() const;
QString group() const;
QString includeFile() const;
QString name() const;
QString toolTip() const;
QString whatsThis() const;
QWidget *createWidget(QWidget *parent);
void initialize(QDesignerFormEditorInterface *core);
private:
bool initialized;
};
关键点:
基类QDesignerCustomWidgetInterface的虚函数重写
#include <QtUiPlugin/QDesignerCustomWidgetInterface>
#include <QtDesigner/QtDesigner>
class MyProgressBar1Interface : public QObject, public QDesignerCustomWidgetInterface
{
Q_OBJECT
Q_INTERFACES(QDesignerCustomWidgetInterface)
...
...
...
}
2、插件的自定义控件类接口
控件继承的基类、控件属性、控件绘制、信号/槽、事件等常规的自定义控件实现,具体参考QPainter的使用
#pragma once
#include <QProgressBar>
#include <QFont>
#include <QColor>
#include <QBrush>
#include <QPen>
#include <QtDesigner/QtDesigner>
class QDESIGNER_WIDGET_EXPORT MyProgressBar1 :
public QProgressBar
{
Q_OBJECT
Q_PROPERTY(QFont textFont READ getTextFont WRITE setTextFont)
Q_PROPERTY(QColor textColor READ getTextColor WRITE setTextColor)
Q_PROPERTY(QPen circleLinePen READ getCircleLinePen WRITE setCircleLinePen)
Q_PROPERTY(QBrush barBackgroundBrush READ getBarBackgroundBrush WRITE setBarBackgroundBrush)
Q_PROPERTY(QBrush barForegroundBrush READ getBarForegroundBrush WRITE setBarForegroundBrush)
public:
explicit MyProgressBar1(QWidget* parent = nullptr);
virtual ~MyProgressBar1();
protected:
virtual void paintEvent(QPaintEvent* event);
public:
QFont getTextFont() const;
void setTextFont(const QFont& font);
QColor getTextColor() const;
void setTextColor(const QColor& color);
QPen getCircleLinePen() const;
void setCircleLinePen(const QPen& pen);
QBrush getBarBackgroundBrush() const;
void setBarBackgroundBrush(const QBrush& brush);
QBrush getBarForegroundBrush() const;
void setBarForegroundBrush(const QBrush& brush);
private:
QFont textFont; //字体格式
QColor textColor; //字体颜色
QPen circleLinePen; //圆轮廓画笔
QBrush barBackgroundBrush; //进度条底色画刷
QBrush barForegroundBrush; //进度条画刷
private:
void InitUi();
void TestPainter();
};
2.2、类接口导出
- 使用QDESIGNER_WIDGET_EXPORT声明类,这个宏所在头文件是#include <QtDesigner/QtDesigner>
#include <QtDesigner/QtDesigner>
class QDESIGNER_WIDGET_EXPORT MyProgressBar1 : public QProgressBar
-
预定义宏QDESIGNER_EXPORT_WIDGETS
这个宏定义如下,所以一定要预定义宏QDESIGNER_EXPORT_WIDGETS,使其能导出接口,不然.dll是编译不过的。
#if defined(QDESIGNER_EXPORT_WIDGETS)
# define QDESIGNER_WIDGET_EXPORT __declspec(dllexport)
#else
# define QDESIGNER_WIDGET_EXPORT __declspec(dllimport)
#endif
二、调用自定义控件插件
1、动态调用插件
实现原理:主要通过.dll工程中的WidgetCollectionInterface、MyProgressBar1Interface等类来实现。先将所有自定义控件类装载到WidgetCollection,调用时再通过name()索引出自定义类,然后createWidget()。
用途:为了Qt Designer设计器能够一次性加载自定义控件插件中的所有控件,使用户可以通过拖拽等方式直接使用控件
特别注意:这种调用方式是不可以直接new自定义控件类的,只能通过下面的方式(LoadInterface、CreateCustomWidget)来调用自定义控件类的成员函数
bool CustomWidgetTestDemo::LoadInterface(QString pluginName)
{
QFileInfo pluginFile( QString("%1/%2").arg(QCoreApplication::applicationDirPath()).arg(pluginName));
QString pluginFilePath = pluginFile.absoluteFilePath();
QPluginLoader load(pluginFilePath);
QObject* obj = load.instance(); //加载dll
if (obj != nullptr)
{
m_interface = qobject_cast<CustomWidgetCollectionInterface*>(obj); //加载接口
if (m_interface != nullptr)
{
return true;
}
else
{
QMessageBox::critical(this, "ERROR", QString::fromStdWString(L"CustomWidgetCollectionInterface加载失败!"));
}
}
else
{
QMessageBox::critical(this, "ERROR", QString::fromStdWString(L"<%1>加载失败!").arg(pluginFilePath));
}
return false;
}
template<class T>
T* CustomWidgetTestDemo::CreateCustomWidget(QString name, QWidget* parent)
{
QList<QDesignerCustomWidgetInterface*> widgets = m_interface->customWidgets();
for each (QDesignerCustomWidgetInterface * var in widgets)
{
if (var->name() == name)
{
T* widget;
widget = static_cast<T*>(var->createWidget(parent));
if (widget != nullptr)
{
return widget;
}
break;
}
}
QMessageBox::critical(this, "ERROR", QString::fromStdWString(L"自定义控件<%1>加载失败!").arg(name));
return nullptr;
}
LoadInterface("QtCustomYihPlugin.dll");
MyProgressBar1* myProgressBar1 = CreateCustomWidget<MyProgressBar1>("MyProgressBar1", this);
myProgressBar1->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Preferred);
2、静态调用插件
实现原理:主要通过.dll工程中的自定义控件类前面添加QDESIGNER_WIDGET_EXPORT来实现。实际上就是给.dll定义类接口
用途:为了能够实例化自定义控件类,即new自定义控件对象。.ui文件生成的源码,也是通过new来实例化自定义控件的,即类似下面的代码。
特别注意:与静态调用.dll方法一样,需要设置.lib依赖及其所在路径
MyProgressBar1* myProgressBar1_666;
myProgressBar1_666 = new MyProgressBar1(this);
myProgressBar1_666->setObjectName(QString::fromUtf8("myProgressBar1_1"));
myProgressBar1_666->setGeometry(QRect(320, 60, 271, 191));
myProgressBar1_666->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Preferred);
m_Layout->addWidget(myProgressBar1_666);
三、结语
关于自定义控件的制作、控件插件的调用完整步骤等信息,可以参考以下资料:
互联网博客:<Qt编写自定义控件插件路过的坑及注意事项>
互联网博客:<Qt之自定义插件(for Qt Designer)>
书籍:<Qt Creator快速入门_第三版>
Demo源码(JaneYih PC):
解决方案名:CustomWidgetProject
创建插件工程名:QtCustomYihPlugin
调用插件工程名:CustomWidgetTestDemo
转载请注明出处!!
如有错误之处,请各路大神指点指点~