1.QtDesigner中,提供了接口,可自定义插件,需继承这个抽象类QDesignerCustomWidgetInterface,实现相应的接口。
{
public:
virtual ~QDesignerCustomWidgetInterface() {}
virtual QString name() const = 0; //名字
virtual QString group() const = 0; //即在哪个组显示
virtual QString toolTip() const = 0;
virtual QString whatsThis() const = 0;
virtual QString includeFile() const = 0;
virtual QIcon icon() const = 0;
virtual bool isContainer() const = 0;
virtual QWidget *createWidget(QWidget *parent) = 0;
virtual bool isInitialized() const { return false; }
virtual void initialize(QDesignerFormEditorInterface *core) { Q_UNUSED(core); }
virtual QString domXml() const
{
return QString::fromUtf8("<widget class=\"%1\" name=\"%2\"/>")
.arg(name()).arg(name().toLower());
}
virtual QString codeTemplate() const { return QString(); }
};
2.上图红框内的插件即使用了上述接口,派生为QAxWidgetPlugin。
class QAxWidgetPlugin : public QObject, public QDesignerCustomWidgetInterface
{
Q_OBJECT
Q_PLUGIN_METADATA(IID "org.qt-project.Qt.QDesignerCustomWidget" FILE "activeqt.json")
Q_INTERFACES(QDesignerCustomWidgetInterface)
public:
explicit QAxWidgetPlugin(QObject *parent = 0);
QString name() const override;
QString group() const override;
QString toolTip() const override;
QString whatsThis() const override;
QString includeFile() const override;
QIcon icon() const override;
bool isContainer() const override;
QWidget *createWidget(QWidget *parent) override;
bool isInitialized() const override;
void initialize(QDesignerFormEditorInterface *core) override;
QString domXml() const override;
private:
QDesignerFormEditorInterface *m_core;
};
其中createWidget,用于创建实际对象,注意,这里是存在于QtDesigner中的对象实例。我们可以看到,当我们拖动QAxWidget放于界面时,其创建的并不是QAxWideget实例,而是QDesignerAxWidget实例。
QWidget *QAxWidgetPlugin::createWidget(QWidget *parent)
{
// Construction from Widget box or on a form?
const bool isFormEditor = parent != 0 && QDesignerFormWindowInterface::findFormWindow(parent) != 0;
QDesignerAxWidget *rc = new QDesignerAxPluginWidget(parent);
if (!isFormEditor)
rc->setDrawFlags(QDesignerAxWidget::DrawFrame|QDesignerAxWidget::DrawControl);
return rc;
}
一般来说,像QPushButton这样的控件,拖动至界面时直接就会创建QPushButton实例。
至于QAxWideget,由于这个插件可用于加载第三方的一些东西,但是在设计时我们没必要显示其具体功能,所以根本就不用直接在QtDesigner中显示,只需要画个框出来告诉位置即可。这可以省去不必要的开销。
3.当我们用QtDesigner设计完后,将会输出.ui文件,上述接口则通过QString QAxWidgetPlugin::domXml() const输出。
QString QAxWidgetPlugin::domXml() const
{
return QStringLiteral("\
<ui language=\"c++\">\
<widget class=\"QAxWidget\" name=\"axWidget\">\
<property name=\"geometry\">\
<rect>\
<x>0</x>\
<y>0</y>\
<width>80</width>\
<height>70</height>\
</rect>\
</property>\
</widget>\
</ui>");
}
下图截取.ui文件。
至此,导出.ui后,QtDesigner的任务已经结束,下面将到重头戏,即通过QUiLoader来加载.ui文件,对于QAxWidget的实例化。
4.一般来说,使用QUiLoader,动态加载完.ui获取QWidget实例后,我们通过调用这个QWidget的findchild来获取ui中的控件,但是却发现无法通过findchild来找到QAxWidget对象,十分诡异。
首先我们看一下QAxWidget这个类
class QAxWidget : public QWidget, public QAxBase
{
Q_OBJECT_FAKE
//...
我们可以看到,Q_OBJECT_FAKE,该类并没有加上Q_OBJECT这个宏,因此QAxWidget实例并不可以通过findchild来获得。
那么我们该怎么获得该实例呢?目前的做法是遍历QWidget实例,然后创建新的QAxWidget,复制相应的属性,然后将指针加到自己创建的QList< QAxWidget >中,并且将原来的QAxWidget对象释放。。十分蛋疼。。