关于自定义控件--插件法
VS + QT 自定义控件
(提升法参考:Qt将两个组件封装成一个组件(自定义接口函数)_qt怎么把两个项目整合成一个-CSDN博客)
1、参考链接
QT中自定义控件的创建到封装到工具栏过程(一):自定义控件的创建_qt 工具栏添加控件-CSDN博客
2、说明
使用QTCreator是可以的
注意事项:
1.新项目使用的时候加入lib库,引用头文件就ok,如果是用Debug构建的,那对应的也只能用于Debug下的项目
2.如果designer界面无显示则需要把release模式下发布的dll与lib放入C:\Qt\Qt5.12.3\5.12.3\msvc2017_64\plugins\designer
3.
这个QDESIGNER_WIDGET_EXPORT必加(对于QtCreator),我们进行控件封装的时候要加,引用该控件的话不需要加,去掉该宏
4.如果带有UI文件,#include "ui_qclasstest4.h"这个需要放在CPP文件中,然后在头文件中还需要一系列声明,可参考例子2.2
5.createWidget函数与name()函数的类名要一样
6.domxml函数"<widget class=\"QArrowLine\" name=\"arrowLine\">\n",注意这两个名字不是一样的,一个是类类型,一个是类名字
2.1 以下为不添加UI文件的示例:
#ifndef QTTESTWIDGET_H
#define QTTESTWIDGET_H
#include <QWidget>
#include <QtUiPlugin/QDesignerExportWidget>
class QDESIGNER_WIDGET_EXPORT QtTestWidget : public QWidget
{
Q_OBJECT
public:
QtTestWidget(QWidget *parent = 0);
};
#endif // QTTESTWIDGET_H
#include "qttestwidget.h"
#include "qpushbutton.h"
QtTestWidget::QtTestWidget(QWidget *parent) :
QWidget(parent)
{
QPushButton *button = new QPushButton(this);
button->setText("custom button");
}
2.2 带UI文件
#ifndef QCLASSTEST4_H
#define QCLASSTEST4_H
#include <QWidget>
#include <QtUiPlugin/QDesignerExportWidget>
namespace Ui {
class QCLASSTEST4;
}
class QDESIGNER_WIDGET_EXPORT QCLASSTEST4 : public QWidget
{
Q_OBJECT
public:
explicit QCLASSTEST4(QWidget *parent = nullptr);
~QCLASSTEST4();
private:
Ui::QCLASSTEST4 *ui;
};
#endif // QCLASSTEST4_H
#include "qclasstest4.h"
#include "ui_qclasstest4.h"
QCLASSTEST4::QCLASSTEST4(QWidget *parent) :
QWidget(parent),
ui(new Ui::QCLASSTEST4)
{
ui->setupUi(this);
}
QCLASSTEST4::~QCLASSTEST4()
{
delete ui;
}
#include "qttestwidget.h"
#include "qttestwidgetplugin.h"
#include <QtPlugin>
#include "testwidget2.h"
#include "classtestwidget2.h"
#include "qclasstestwidget3.h"
#include "qclasstest4.h"
QtTestWidgetPlugin::QtTestWidgetPlugin(QObject *parent)
: QObject(parent)
{
m_initialized = false;
}
void QtTestWidgetPlugin::initialize(QDesignerFormEditorInterface * /* core */)
{
if (m_initialized)
return;
// Add extension registrations, etc. here
m_initialized = true;
}
bool QtTestWidgetPlugin::isInitialized() const
{
return m_initialized;
}
QWidget *QtTestWidgetPlugin::createWidget(QWidget *parent)
{
return new QCLASSTEST4(parent);
}
QString QtTestWidgetPlugin::name() const
{
return QLatin1String("QCLASSTEST4");
}
QString QtTestWidgetPlugin::group() const
{
return QLatin1String("My Plugins");
}
QIcon QtTestWidgetPlugin::icon() const
{
return QIcon();
}
QString QtTestWidgetPlugin::toolTip() const
{
return QLatin1String("");
}
QString QtTestWidgetPlugin::whatsThis() const
{
return QLatin1String("");
}
bool QtTestWidgetPlugin::isContainer() const
{
return false;
}
QString QtTestWidgetPlugin::domXml() const
{
return QLatin1String("<widget class=\"QCLASSTEST4\" name=\"mQCLASSTEST4\">\n</widget>\n");
}
QString QtTestWidgetPlugin::includeFile() const
{
return QLatin1String("qclasstest4.h");
}
#if QT_VERSION < 0x050000
Q_EXPORT_PLUGIN2(qttestwidgetplugin, QtTestWidgetPlugin)
#endif // QT_VERSION < 0x050000
3、关于在同一个DLL中封装多个自定义控件
参考链接:Qt-QtDesigner插件编写_qdesignercustomwidgetcollectioninterface-CSDN博客
介绍:
Plugin结尾的类用于提供有用的组件信息给Qt Designer,非Plugin结尾的类表示自定义组件的实现。每一个组件都需要一个Plugin类
bool isContainer() const;//组件是否为容器,容器可包含其他QWidget
bool isInitialized() const;//是否已经初始化
QIcon icon() const;//Designer中的Widget Box的icon
QString domXml() const;//组件的属性描述。主要包括拖入时的默认大小
QString group() const;//Designer中的Widget Box的分组
QString includeFile() const;//uic自动生成时自动包括的头文件
QString name() const;//组件名称
QString toolTip() const;//Designer中组件tips
QString whatsThis() const;//Designer中组件详细说明
QWidget *createWidget(QWidget *parent);//创建组件
void initialize(QDesignerFormEditorInterface *core);//初始化组件
注意:
如果是多个控件,每个组件的plug类都需要把下图中Q_PLUGIN_METADATA注释掉

创建一个管理类,用来管理多个组件plug,参考如下图
#pragma once
#include <QObject>
#include <QtUiPlugin/QDesignerCustomWidgetCollectionInterface>
class CustomWidgets : public QObject, public QDesignerCustomWidgetCollectionInterface
{
Q_OBJECT
Q_PLUGIN_METADATA(IID "org.qt-project.Qt.QDesignerCustomWidgetCollectionInterface")
Q_INTERFACES(QDesignerCustomWidgetCollectionInterface)
public:
CustomWidgets(QObject* parent = 0);
QList<QDesignerCustomWidgetInterface*> customWidgets() const override;
private:
QList<QDesignerCustomWidgetInterface*> widgets;
};
#include "QtClass2.h"
#include "QtDesignerWidget2Plugin.h"
#include "QtClassPlugin2.h"
#include <QtCore/QtPlugin>
CustomWidgets::CustomWidgets(QObject* parent)
: QObject(parent)
{
widgets.append(new QtDesignerWidget2Plugin(this));
widgets.append(new QtClassPlugin2(this));
}
QList<QDesignerCustomWidgetInterface*> CustomWidgets::customWidgets() const
{
return widgets;
}
4、关于VS下封装自定义控件
目前不带UI的控件可以,QDESIGNER_WIDGET_EXPORT可以不需要这个引申,
Q_DECL_EXPORT 用这个宏来代替,需要注意封装控件dll的时候要加该宏,如果对应的给其他项目调用该控件的话一般需要把这个宏去掉
进阶方式使用宏定义来进行一个判断(在封装dll项目中添加宏定义,可以右键点击工程-->属性-->c/c++-->预处理器-->预处理器定义)
#ifdef QtDesignerWidget3Test
class Q_DECL_EXPORT SwitchButton : public QWidget
#else
class SwitchButton : public QWidget
#endif
示例程序如下
#pragma once
#include <QtWidgets/QWidget>
#include <QtUiPlugin/QDesignerExportWidget>
class QtDesignerWidget2 : public QWidget
{
Q_OBJECT
public:
QtDesignerWidget2(QWidget *parent = nullptr);
};
#include "QtDesignerWidget2.h"
#include "QPushButton"
QtDesignerWidget2::QtDesignerWidget2(QWidget *parent)
: QWidget(parent)
{
QPushButton *button = new QPushButton(this);
button->setText("custom button");
}
5、给自定义控件加属性栏
参考链接:Qt之自定义属性Q_PROPERTY专题(1)充分理解其概念以及用途-WinFrom控件库|.net开源控件库|HZHControls官网
一个属性的行为就像类的数据成员,但是它还具有附加的特性,这些特性可以被元数据对象系统操作。这些特性是:
需要一个READ访问器函数。用于读属性的值。理想情况下,有一个不变的函数用于此目的,并且它必须返回属性的类型的值或指针或引用。例如,QWidget::focus是一个只读的属性,它对应一个读函数:QWidget::hasFocus()。
一个可选的WRITE访问器函数。它用于设置属性的值。它必须返回空并且至少具有一个参数,参数是属性类型的值或指针或引用。例如:QWidget::enabled具有WRITE函数QWidget::setEnable()。只读属性不需要写函数。例如,QWidget::focus没有对应的写函数。
一个可选的RESET函数。用于设置属性的值到它的默认值。例如:QWidget::cursor具有典型的READ和WRITE函数,QWidget::cursor()和QWidget::setCursor(),并且它也具有一个RESET函数,QWidget::unsetCursor()。RESET函数必须返回void并且不带有任何参数。
一个可选的NOTIFY信号。如果被定义了,信号将在属性的值改变时发出。信号必须带有一个参数,这个参数的类型必须与属性相同;参数保存的是属性的新值。
一个DESIGNABLE变量表明此属性是否在界面设计器的属性编辑器中出现。大多数属性是可见的,除了为这个变量传入true或false,你还可以指定一个bool型的成员函数。
SCRIPTABLE变量表明这个属性是否可以被一个脚本引擎操作(默认是true)。你也可以赋予它true或false或bool型函数。
STORED变量表明了属性是否被认为是独立存在还是依赖于其它的值而存在。它也表明是否在保存对象状态时保存此属性的值。大多数属性都是需要保存的,但是,如QWidget::minimumWidth()就是不被保存的,因为它的值是从另一个属性QWidget::minimumSize()得来的。
USER变量表明属性是否被设计为面向用户的或用户可修改的类属性。通常,每个类只有一个USER属性。例如,QAbstractButton::checked是按钮类的用户可修改属性。注意QItemDelegate获取和设置widget的USER属性。
CONSTANT的出现表明属性的值是不变的。对于一个object实例,常量属性的READ方法在每次被调用时必须返回相同的值。此常量值可能在不同的object实例中不相同。一个常量属性不能具有WRITE方法或NOYIFY信号。
FINAL变量的出现表明属性不能被派生类所重写。有些情况下,这可以用于效率优化,但不是被moc强制的。程序员必须永远注意不能重写一个FINAL属性。
READ,WRITE和RESET函数都可以被继承。它们也可以是虚函数。当它们在被多重继承中被继承时,它们必须出现在第一个被继承的类中。属性的类型可以是被QVariant支持的所有类型,也可以是用户定义的类型。在下面的例子中,类QDate被当作用户自定义类型。
Q_PROPERTY(QDate data READ getDate WRITE setDate)
因为QDate是用户定义的,你必须包含<QDate>头文件。
对于QMap,QList和QValueList属性,属性的值是一个QVariant,它包含整个list或map。注意Q_PROPERTY字符串不能包含逗号,因为逗号会划分宏的参数。因此,你必须使用QMap作为属性的类型而不是QMap<QString,QVariant>。为了保持一致性,也需要用QList和QValueList而不是QList<QVariant>和QValueList<QVariant>。
1.在头文件进行声明
Q_PROPERTY(QString m_text READ getText WRITE setText)
QString m_text 自定义变量
READ,WRITE 关键词
getText,setText 自定义函数 getText为const修饰不变的
2.示例代码
#ifndef QCLASSTEST4_H
#define QCLASSTEST4_H
#include <QWidget>
#include <QtUiPlugin/QDesignerExportWidget>
namespace Ui {
class QCLASSTEST4;
}
class QDESIGNER_WIDGET_EXPORT QCLASSTEST4 : public QWidget
{
Q_OBJECT
Q_PROPERTY(QString m_text READ getText WRITE setText)
public:
explicit QCLASSTEST4(QWidget *parent = nullptr);
~QCLASSTEST4();
QString getText() const
{
return m_text;
}
void setText(QString s);
private:
Ui::QCLASSTEST4 *ui;
QString m_text;
};
#endif // QCLASSTEST4_H
#include "qclasstest4.h"
#include "ui_qclasstest4.h"
QCLASSTEST4::QCLASSTEST4(QWidget *parent) :
QWidget(parent),
ui(new Ui::QCLASSTEST4)
{
ui->setupUi(this);
}
QCLASSTEST4::~QCLASSTEST4()
{
delete ui;
}
void QCLASSTEST4::setText(QString s)
{
m_text = s;
ui->label->setText(s);
}
注意:
如果像有枚举类型这种特殊类型,需要加头文件进行引用
例如:
Q_OBJECT
Q_ENUMS(ButtonStyle)
Q_PROPERTY(int space READ getSpace WRITE setSpace)
Q_ENUMS 是 Qt 提供的一种宏,用于将一个枚举类型注册为 Qt 的元对象系统中的一个类型。这样,我们就可以使用 Qt 的反射机制来操作这个枚举类型,比如通过字符串名字来查找枚举值,或者在 Qt 的各种属性框架中使用这个枚举类型等。
更多推荐

所有评论(0)