每次使用Qt进行编写好自定义控件后,还需要编写Desginer设计器使用的插件。才能够提供给Designer设计器使用,过程比较繁琐,工作量也比较大,不够灵活。本文介绍怎样使用之前技术博文提及到的动态创建技术实现脚本化管理Designer自定义控件插件。
首先介绍下管理脚本文件结构
libs节点:自定义控件库集合;
directory属性:表示自定义控件库的存储路径;
lib节点:描述一个自定义控件库;
name节点:自定义控件库名称;
method节点:控件创建方法入口;
controls节点:控件集合;
control节点:描述一个控件;
name属性:控件名称;
container节点:是否为容器;
icon节点:Designer设计器中显示控件图标描述;
directory属性:图标存储路径;
name节点:图标名称;
doxml节点:控件默认ui的描述信息;
脚本解析类声明如下:
class DomControls;
class DomLibs;
class DomControl;
class DomLib;
class DomInclude;
class DomIcon;
class DomDomXml;
class DomName;
class DomContainer;
class DomCollections
{
public:
DomCollections();
~DomCollections();
void read(const QDomElement& node);
void setElementLibs(DomLibs* libs);
void setElementControls(DomControls* controls);
DomControls *elementControls()const;
DomLibs *elementLibs()const;
void setAttributeVersion(const QString& version);
QString attributeVersion()const;
bool hasAttributeVersion()const;
void clearAttributeVersion();
private:
QString m_attr_version;
bool m_has_attr_version;
DomControls* m_controls;
DomLibs* m_libs;
};
class DomLibs{
public:
DomLibs();
~DomLibs();
void read(const QDomElement& node);
void setElementLib(DomLib* lib);
QList<DomLib *> elementLib()const;
void setAttributeDirectory(const QString& dir);
QString attributeDirectory()const;
bool hasAttributeDirectory()const;
void clearAtrributeDirectory();
private:
QString m_attr_directory;
bool m_has_attr_directory;
QList<DomLib*> m_libs;
};
class DomControls{
public:
DomControls();
~DomControls();
void read(const QDomElement& node);
void setElementControl(DomControl* control);
QList<DomControl *> elementControl()const;
private:
QList<DomControl*> m_controls;
};
class DomLib{
public:
DomLib();
~DomLib();
void read(const QDomElement& node);
void setElementName(const QString& name);
QString elementName()const;
void setElementMethod(const QString& method);
QString elementMethod()const;
private:
QString m_name;
QString m_method;
};
class DomControl{
public:
DomControl();
~DomControl();
void read(const QDomElement& node);
void setElementContainer(DomContainer* container);
DomContainer *elementContainer()const;
void setElementIcon(DomIcon* icon);
DomIcon *elementIcon()const;
void setElementInclude(DomInclude* include);
DomInclude* elementInclude()const;
void setElementDomXml(DomDomXml* domxml);
DomDomXml *elementDomXml()const;
void setAttributeName(const QString& name);
QString attributeName()const;
bool hasAttributeName()const;
void clearAttributeName();
private:
bool m_has_attr_name;
QString m_attr_name;
DomContainer* m_container;
DomIcon* m_icon;
DomInclude* m_include;
DomDomXml* m_domxml;
};
class DomContainer{
public:
DomContainer();
~DomContainer();
void read(const QDomElement& node);
void setElementContainter(bool container);
bool elementContainter()const;
private:
bool m_container;
};
class DomIcon{
public:
DomIcon();
~DomIcon();
void read(const QDomElement& node);
void setElementName(const QString& name);
QString elementName()const;
void setAttributeDirectory(const QString& dir);
QString attributeDirectory()const;
bool hasAttributeDirectory()const;
void clearAttributeDirectory();
private:
bool m_has_attr_directory;
QString m_attr_directory;
QString m_name;
};
class DomInclude{
public:
DomInclude();
~DomInclude();
void read(const QDomElement& node);
void setElementInclude(const QString& include);
QString elementInclude()const;
private:
QString m_include;
};
class DomDomXml{
public:
DomDomXml();
~DomDomXml();
void read(const QDomElement& node);
void setElementDomXml(const QString& domxml);
QString elementDomXml()const;
private:
QString m_domxml;
};
class DomBaseType{
public:
DomBaseType();
~DomBaseType();
void read(const QDomElement& node);
void setElementBool(bool v);
bool elementBool()const;
void setElementName(QString name);
QString elementName()const;
void setElementString(QString string);
QString elementString()const;
void setElementMethod(QString method);
QString elementMethod()const;
private:
QString m_name;
QString m_string;
QString m_method;
bool m_bool;
};
脚本结构设计好,接下来我们就可以编写动态加载插件的逻辑,这样我们就可以通过解析脚本中的相关信息,然后使用动态创建的办法,加载我们的控件。
动态加载插件相关类声明如下:
class CustomWidgetInterface: public QObject,
public QDesignerCustomWidgetInterface
{
Q_OBJECT
Q_INTERFACES( QDesignerCustomWidgetInterface )
public:
CustomWidgetInterface( QObject *parent );
virtual bool isContainer() const;
virtual bool isInitialized() const;
virtual QIcon icon() const;
virtual QString codeTemplate() const;
virtual QString domXml() const;
virtual QString group() const;
virtual QString includeFile() const;
virtual QString name() const;
virtual QString toolTip() const;
virtual QString whatsThis() const;
virtual void initialize( QDesignerFormEditorInterface * );
protected:
QString d_name;
QString d_include;
QString d_toolTip;
QString d_whatsThis;
QString d_domXml;
QString d_codeTemplate;
QIcon d_icon;
bool d_isContainer;
private:
bool d_isInitialized;
};
typedef QWidget* (*CreateObjectFunc)(QWidget* parent, QString className);
class CustomWidgetCollectionInterface: public QObject,
public QDesignerCustomWidgetCollectionInterface
{
Q_OBJECT
Q_INTERFACES( QDesignerCustomWidgetCollectionInterface )
#if QT_VERSION >= 0x050000
Q_PLUGIN_METADATA(IID "org.qt-project.Qt.QDesignerCustomWidgetCollectionInterface" )
#endif
public:
CustomWidgetCollectionInterface( QObject *parent = NULL );
virtual ~CustomWidgetCollectionInterface();
virtual QList<QDesignerCustomWidgetInterface*> customWidgets() const;
private:
QList<QDesignerCustomWidgetInterface*> d_plugins;
void readCollections();
TMCONTROLS::DomCollections* d_collections;
};
class CtmControlsInterface: public CustomWidgetInterface
{
Q_OBJECT
Q_INTERFACES( QDesignerCustomWidgetInterface )
public:
CtmControlsInterface( QObject *parent );
virtual QWidget *createWidget( QWidget *parent );
void setDomContainter(bool isContainer);
void setDomInclude(const QString& domInclude);
void setDomXml(const QString& domXml);
void setDomName(const QString& domName);
void setDomIcon(const QPixmap& domPixmap);
static void addCreateMethod(CreateObjectFunc method);
private:
inline static QList<CreateObjectFunc>& createObjectMethods(){
static QList<CreateObjectFunc> _createObjectsMethods;
return _createObjectsMethods;
}
};
class TaskMenuFactory: public QExtensionFactory
{
Q_OBJECT
public:
TaskMenuFactory( QExtensionManager *parent = 0 );
protected:
QObject *createExtension( QObject *object,
const QString &iid, QObject *parent ) const;
};
class TaskMenuExtension: public QObject,
public QDesignerTaskMenuExtension
{
Q_OBJECT
Q_INTERFACES( QDesignerTaskMenuExtension )
public:
TaskMenuExtension( QWidget *widget, QObject *parent );
QAction *preferredEditAction() const;
QList<QAction *> taskActions() const;
private Q_SLOTS:
void editProperties();
void applyProperties( const QString & );
private:
QAction *d_editAction;
QWidget *d_widget;
};
由于代码较多,有兴趣的朋友可以前往下载
编译安装后,之后再编编译好的自定义库,只需要在脚本中定义好,就可以加载进设计器中使用,最终的效果如下: