之前Blog里面有关于QWT的编译、配置、使用的文章,分别是在VS与Creator下进行的。

    里面介绍了如何将QWT集成到Designer中。如果认真研究过的话,那么对Designer中使用插件应该就不再陌生了。
    下面介绍下自己如何去实现一个插件并将其应用到Designer中。
 
插件介绍:
    Qt Designer基于插件的架构允许用户自定义和第三方的自定义窗口部件进行编辑,就像用标准的Qt控件一样。所有的自定义部件功能提供给Qt Designer,包括部件属性,信号和槽。由于Qt Designer在设计过程中采用真实部件,所以预览的时候自定义部件会和设计阶段的一样。
    好的,那先上一个预览的效果吧!
    如图,Designer中包含了自定义插件(Clock、Qled)以及第三方插件(QWT),好的,先看看效果,后面会有具体讲解怎么实现的,慢慢来。。。
 
    要为Qt Designer集成自定义窗口部件,则需要一个合适的窗口部件和适当的.pro文件。
 
提供了一个接口描述
    为了通知Qt Designer想要提供窗口部件的类型,则需要创建一个QDesignerCustomWidgetInterface的子类,其中描述了部件暴露的各种属性,其大多数是由基类中的纯虚函数提供的,因为只有插件的作者可以提供这方面的信息。

编号

函数

返回值描述

1

name()

提供了插件的类名称

2

group()

该控件所属的组中的Qt Designer的小工具盒

3

toolTip()

一个简短的说明,以帮助用户识别Qt Designer中的部件

4

whatsThis()

为Qt Designer用户设计的部件一个较长的描述

5

includeFile()

头文件必须包含在使用该插件的应用程序的。此信息存储在UI文件中,并将由UIC创建用于包含自定义插件形式的代码合适的#includes语句。

6

icon()

Qt Designer的插件箱中小窗口的图标

7

isContainer()

true表示部件将用来保存子部件,否则为false

8

9

10

createWidget()

domXml()

codeTemplate()

一个指向自定义窗口小部件的QWidget指针实例,构建了所提供的父母。

注:createWidget()是一个工厂方法,只负责创建小部件的功能。自定义窗口小部件的属性将不可用,直到load()返回。

描述了部件的属性,例如:对象名称、大小提示,以及其它标准的QWidget属性的描述。

这个函数是预留给Qt Designer将来使用的

 
    其它两个虚函数也可以重新实现

编号

函数

返回值描述

11

initialize()

设置了自定义窗口部件扩展等功能。自定义容器扩展(见QDesignerContainerExtension)和任务菜单扩展(见QDesignerTaskMenuExtension)应在此函数中设置。

12

isInitialized()

如果该部件已被初始化,则返回true;否则返回false。重新实现通常检查initialize()函数是否已被调用,并返回本次测试的结果。

   
 
domXml() 函数的注意事项:
    domXml()函数返回一个UI文件代码段,使用Qt Designer窗口工厂创建一个自定义窗口部件和使用特性。
    从Qt4.4开始,Qt Designer的窗口部件中允许一个完整的UI文件来描述一个自定义窗口部件。UI文件可以使用标签加载。指定标签允许添加元素,其中包含自定义窗口部件的其它信息。如果不需要更多的信息,那么标签已经足够了。
    如果自定义窗口部件不提供合理的尺寸,有必要通过在子类的domXml()函数返回的字符串中指定默认的位置大小(geometry)。例如,由自定义的Widget插件示例提供的AnalogClockPlugin,通过下面的方式来指定默认的部件位置大小:
 
    ...
" \n"
" \n"
" 0\n"
" 0\n"
" 100\n"
" 100\n"
" \n"
" \n"
...
    domXml()函数的另一个特点是,如果它返回一个空字符串,部件不会安装在Qt Designer的窗口部件盒中。然而,它仍然可以被其它形式的部件所使用。这个特性用来隐藏部件,不应由用户显式地创建,但需要其它部件创建。
     一个完整的自定义部件格式是这样的:
 displayname="MyWidget">

            widgets::MyWidget
addPage
标签的属性:
属性 呈现形式 内容
language 可选项 "c++",
"jambi"
这个属性指定了自定义窗口部件提供的语言。
主要有防止C++插件出现在Qt Jambi中。
displayname 可选项 类名 属性的值将出现在小工具框,可以用来剥去命名空间。
    标签告诉Qt Designer和UIC应采用哪种方法将页面添加到一个容器组件中。这适用于容器构件需要调用特定的方法来添加一个孩子,而不是通过父亲来添加孩子。特别是,这是相关的容器,不是一个Qt Designer提供的子类容器,但是基于当前页面的概念。此外,您需要提供一个容器扩展他们。
    元素可以包含属性的元信息的列表。目前,支持字符串类型的属性。对于这些属性,所述标记都可以使用。该标签具有以下属性:
 
属性 呈现形式 内容
name 必须的 该属性的名称
type 必须 见下表 该属性的值决定了属性编辑器将如何处理它们。
notr 可选项 "true",
"false"
如果属性是“true”,则该值意味着不再被翻译。
字符串属性的类型属性的值:
类型
"richtext" 富文本
"multiline" 多行纯文本
"singleline" 单行纯文本
"stylesheet" 一个CSS样式表
"objectname" 对象名称(受限制的一组有效字符)
"url" URL、文件名.
插件要求
    为了让插件在所有平台上正常工作,你需要确保他们导出了Qt Designer所需要的符号。
    首先,插件类必须被Qt Designer加载的插件按顺序导出。使用Q_PLUGIN_METADATA()宏来做到这一点。此外,QDESIGNER_WIDGET_EXPORT宏必须被使用,来定义Qt Designer将实例化的插件中每一个自定义窗口部件类。
 
创建一个良好的插件:
    一些自定义窗口部件有专门的用户界面功能,可以使他们的行为不同于Qt Designer中的其它标准窗口部件。特别是,如果一个自定义小部件由于调用QWidget::grabKeyboard()来捕获键盘,Qt Designer的操作将受到影响。
    为了让自定义部件在Qt Designer有特殊行为,提供 initialize()函数来配置窗口部件运行过程中的特定行为。该函数在被第一次调用之前先调用createWidget(),可以设定一个内部标志来测试什么时候调用createWidget()函数。
 
1.构建插件
    为了简单期间,这里只提供QLed的源码,customwidgetplugin的源码可在安装目录中的Demo里面查找(例:D:\Qt\Qt5.1.1\5.1.1\msvc2010\examples\designer\customwidgetplugin)。
 
qledplugin.pro
#CONFIG      += designer plugin debug_and_release
#TARGET = $$qtLibraryTarget($$TARGET)
#TEMPLATE = lib
#QT += svg #QTDIR_build:DESTDIR = $$QT_BUILD_TREE/plugins/designer CONFIG += plugin
CONFIG += designer
CONFIG += debug_and_release
TEMPLATE = lib
QT += svg widgets designer HEADERS = qled.h \
qledplugin.h
SOURCES = qled.cpp \
qledplugin.cpp RESOURCES = qled.qrc target.path = $$[QT_INSTALL_PLUGINS]/designer
INSTALLS += target sources # install
#target.path = $$[QT_INSTALL_PLUGINS]/designer
#sources.files = $$SOURCES $$HEADERS *.pro
#sources.path = $$[QT_INSTALL_EXAMPLES]/designer/qledplugin
#INSTALLS += target sources
qled.h
#ifndef QLED_H
#define QLED_H #include <</span>Qt>
#include <</span>QWidget>
#include <</span>QtDesigner/QDesignerExportWidget> class QColor;
class QSvgRenderer; class QDESIGNER_WIDGET_EXPORT QLed : public QWidget
{
Q_OBJECT
Q_ENUMS (ledColor)
Q_ENUMS (ledShape)
Q_PROPERTY(bool value READ value WRITE setValue);
Q_PROPERTY(ledColor onColor READ onColor WRITE setOnColor);
Q_PROPERTY(ledColor offColor READ offColor WRITE setOffColor);
Q_PROPERTY(ledShape shape READ shape WRITE setShape) public:
QLed(QWidget *parent = 0);
virtual ~QLed();
bool value() const { return m_value; }
enum ledColor { Red=0,Green,Yellow,Grey,Orange,Purple,Blue };
enum ledShape { Circle=0,Square,Triangle,Rounded};
ledColor onColor() const { return m_onColor; }
ledColor offColor() const { return m_offColor; }
ledShape shape() const { return m_shape; } public slots:
void setValue(bool);
void setOnColor(ledColor);
void setOffColor(ledColor);
void setShape(ledShape);
void toggleValue(); protected:
bool m_value;
ledColor m_onColor, m_offColor;
int id_Timer;
ledShape m_shape;
QStringList shapes;
QStringList colors;
void paintEvent(QPaintEvent *event);
private:
QSvgRenderer *renderer ;
}; #endif
qled.cpp
#include
#include
#include
#include
#include
#include #include "qled.h" QLed::QLed(QWidget *parent)
: QWidget(parent)
{
m_value=false;
m_onColor=Red;
m_offColor=Grey;
m_shape=Circle;
shapes << ":/resources/circle_" << ":/resources/square_" << ":/resources/triang_" << ":/resources/round_";
colors << "red.svg" << "green.svg" << "yellow.svg" << "grey.svg" << "orange.svg" << "purple.svg" << "blue.svg"; renderer = new QSvgRenderer();
}
QLed::~QLed() {
delete renderer;
} void QLed::paintEvent(QPaintEvent *)
{ QString ledShapeAndColor;
QPainter painter(this);
painter.setRenderHint(QPainter::Antialiasing, true); ledShapeAndColor=shapes[m_shape]; if(m_value)
ledShapeAndColor.append(colors[m_onColor]);
else
ledShapeAndColor.append(colors[m_offColor]); renderer->load(ledShapeAndColor);
renderer->render(&painter); } void QLed::setOnColor(ledColor newColor)
{
m_onColor=newColor;
update();
} void QLed::setOffColor(ledColor newColor)
{
m_offColor=newColor;
update();
} void QLed::setShape(ledShape newShape)
{
m_shape=newShape;
update();
} void QLed::setValue(bool value)
{
m_value=value;
update();
} void QLed::toggleValue()
{
m_value=!m_value;
update();
}
qledplugin.h
#ifndef CUSTOMWIDGETPLUGIN_H
#define CUSTOMWIDGETPLUGIN_H #include <</span>QDesignerCustomWidgetInterface>
class QLedPlugin : public QObject, public QDesignerCustomWidgetInterface
{
Q_OBJECT
Q_PLUGIN_METADATA(IID "org.qt-project.Qt.QDesignerCustomWidgetInterface" FILE "QLedPlugin.json")
Q_INTERFACES(QDesignerCustomWidgetInterface) public:
QLedPlugin(QObject *parent = 0); 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;
}; #endif
qledplugin.cpp
#include "qled.h"
#include "qledplugin.h"
#include <</span>QtPlugin> QLedPlugin::QLedPlugin(QObject *parent)
: QObject(parent)
{
initialized = false;
} void QLedPlugin::initialize(QDesignerFormEditorInterface * )
{
if (initialized)
return; initialized = true;
} bool QLedPlugin::isInitialized() const
{
return initialized;
} QWidget *QLedPlugin::createWidget(QWidget *parent)
{
return new QLed(parent);
} QString QLedPlugin::name() const
{
return "QLed";
} QString QLedPlugin::group() const
{
return "Led Widgets";
} QIcon QLedPlugin::icon() const
{
return QIcon(":resources/qled.png");
} QString QLedPlugin::toolTip() const
{
return tr("Led Custom widget Plugin fot Qt Designer");
} QString QLedPlugin::whatsThis() const
{
return tr("Led Custom widget Plugin fot Qt Designer");
} bool QLedPlugin::isContainer() const
{
return false;
} QString QLedPlugin::domXml() const
{
return "\n"
" \n"
" \n"
" 0\n"
" 0\n"
" 50\n"
" 50\n"
" \n"
" \n"
" \n"
" Binary Led\n"
" \n"
" \n"
" false\n"
" \n"
" \n"
" Led widget\n"
" \n"
" \n"
" QLed::Red\n"
" \n"
" \n"
" QLed::Grey\n"
" \n"
" \n"
" QLed::Circle\n"
" \n"
"\n";
} QString QLedPlugin::includeFile() const
{
return "qled.h";
}
    我相信到这里所有的东西都已经很清楚了,记得不要忘记QLedPlugin.json文件喔,当然最后也不能少资源文件:

    经过编译,后会生成一个qledplugin.lib与qledplugin.dll,
 
2.配置插件
    qt安装目录以D:\Qt\Qt5.1.1\5.1.1\msvc2010为例:
(1)将编译好的qledplugin.dll拷贝到D:\Qt\Qt5.1.1\5.1.1\msvc2010\bin目录下,
   将qledplugin.lib拷贝到D:\Qt\Qt5.1.1\5.1.1\msvc2010\lib下
(2)将qledplugin.dll拷贝到D:\Qt\Qt5.1.1\5.1.1\msvc2010\plugins\designer目录下。
(3)将qled.h和qled.cpp放入一个空文件夹QLed中,再将该文件夹拷贝到D:\Qt\Qt5.1.1\5.1.1\msvc2010\include目录下。
 
3.使用插件
 新建项目,然后进行配置,主要看下.pro的写法,如下:  
QT       += core gui svg

greaterThan(QT_MAJOR_VERSION, 4): QT += widgets

TARGET = TestCustomWidgetPlugin
TEMPLATE = app INCLUDEPATH += $$(QTDIR)/include/QCustomWidgetPlugin
INCLUDEPATH += $$(QTDIR)/include/QLed LIBS += $$(QTDIR)/lib/customwidgetplugin.lib \
$$(QTDIR)/lib/qledplugin.lib SOURCES += main.cpp\
widget.cpp HEADERS += widget.h FORMS += widget.ui
这样所有的任务都完成了,很轻松的就可以在designer里面设计并预览了。
 
效果如下:
 
 
注:
    技术在于交流、沟通,转载请注明出处并保持作品的完整性。

Qt之自定义插件(for Qt Designer)的更多相关文章

  1. QT 程序自定义插件

    1,定义接口文件 /****************************************************************************************** ...

  2. Qt编写自定义控件插件路过的坑及注意事项

    在一日一控件的口号下,终于写好了五十几个自定义控件,包括各种仪表盘,各种温度计,各种进度条,各种按钮等,具体可参见(http://www.cnblogs.com/feiyangqingyun/p/61 ...

  3. Qt之自定义搜索框

    简述 关于搜索框,大家都经常接触.例如:浏览器搜索.Windows资源管理器搜索等. 当然,这些对于Qt实现来说毫无压力,只要思路清晰,分分钟搞定. 方案一:调用QLineEdit现有接口 void ...

  4. Qt之自定义检索框

    1.效果展示 今天这篇文章主要讲解的是自定义搜索框,不仅仅支持搜索,而且可以支持搜索预览,具体请看效果图1.网上也有一些比较简单明了的自定义搜索框,比如Qt之自定义搜索框,讲的也比较详细,不过本文的侧 ...

  5. Qt之自定义搜索框——QLineEdit里增加一个Layout,还不影响正常输入文字(好像是一种比较通吃的方法)

    简述 关于搜索框,大家都经常接触.例如:浏览器搜索.Windows资源管理器搜索等. 当然,这些对于Qt实现来说毫无压力,只要思路清晰,分分钟搞定. 方案一:调用QLineEdit现有接口 void ...

  6. Qt自定义插件编程小结

    qt自定义组件开发步骤演示.以下所有步骤的前提是自己先编译Qtcreator源码,最好生成release版的QtCreator,否则自定义的插件嵌入QtCreator会失败!!!(这个网上教程很多) ...

  7. Qt之自定义QLineEdit右键菜单

    一.QLineEdit说明 QLineEdit是单行文本框,不同于QTextEdit,他只能显示一行文本,通常可以用作用户名.密码和搜索框等.它还提供了一些列的信号和槽,方便我们使用,有兴趣的小伙伴可 ...

  8. 【Qt】Qt之自定义搜索框【转】

    简述 关于搜索框,大家都经常接触.例如:浏览器搜索.Windows资源管理器搜索等. 当然,这些对于Qt实现来说毫无压力,只要思路清晰,分分钟搞定. 简述 效果 细节分析 Coding 源码下载 效果 ...

  9. Qt制作应用插件

    在Qt下,插件有两种形式,一种是用于QtCreator下,扩展IDE功能.另一种是用于扩展开发者的应用.本文要讲的是后者. 定义一个纯虚类作为插件接口 #include <QtPlugin> ...

随机推荐

  1. win向linux传文件

    使用pscp.exe即可. 下载pscp.exe(http://pan.baidu.com/s/1jG6zmx4) 复制到windows/system32目录下即可. 然后可在cmd命令行下使用psc ...

  2. 时间处理总结(二)oracle

    不断总结中................. 1.等于land.djsj=to_date('2016/7/26','yyyy-MM-dd')2.大于等于land.djsj>=to_date('2 ...

  3. iOS 图片按比例压缩,指定大小压缩

    使用系统方法UIImageJPEGRepresentation(UIimage *image,CGFloat quality)进行图片质量压缩,暂且叫参数quality为压缩比吧,取值范围为0-1. ...

  4. 类库探源——System.Drawing.Bitmap

    一.System.Drawing.Bitmap Bitmap 类: 封装GDI+ 位图,此位图由图形图像及其属性的像素数据组成.Bitmap 是用于处理由像素定义的图像的对象 命名空间: System ...

  5. UVA 10881 Piotr's Ants(等效变换 sort结构体排序)

    Piotr's AntsTime Limit: 2 seconds Piotr likes playing with ants. He has n of them on a horizontal po ...

  6. IF EXIST: The syntax of the command is incorrect.

    Batch 脚本中使用 IF EXIST 语句时,总是提示 The syntax of the command is incorrect. 原始 bat 脚本如下: ECHO OFF SET proj ...

  7. MySQL配置文件详解

    MYSQL 配置文件详解 “全局缓存”.“线程缓存”,全局缓存是所有线程共享,线程缓存是每个线程连接上数据时创建一个线程(如果没有设置线程池),假如有200连接.那就是200个线程,如果参数设定值是1 ...

  8. ubuntu server 安装

    http://tigerlchen.iteye.com/blog/1765765  解决CDROM找不到的bug

  9. sae后台管理的js(二)

    jsloader cssloader 使用方法<link rel="stylesheet" type="text/css" href="/min ...

  10. react native学习1-安装,执行

    demo地址 http://www.oschina.net/p/reactnative http://my.oschina.net/luyongfugx/blog/394427#OSC_h1_1 翻译 ...