在 Qt Designer 內使用自定義的 widget Part2

| | 0 Comments| 10:59
Categories:

這篇是之前《在 Qt Designer 內使用自定義的 widget》一文的後續。

其實本來 Heresy 一直以為之前使用 QDesignerCustomWidgetInterface 另外封包一個 plugin 物件出來後就搞定了,但是後來才發現,真正要拿來建立函式庫,還是有點問題。

原因就是:如果在一個專案裡面、按照之前的方法寫多個 plugin 出來的話,在建置的連結階段,會出現重複定義的問題。Visual Studio 得到的錯誤會向下面這樣:

錯誤    LNK2005    qt_plugin_instance 已在 moc_plugin2.obj 中定義過了
QtUIforDesigner    moc_Plugin1.obj    1
錯誤    LNK2005    qt_plugin_query_metadata 已在 moc_Plugin2.obj 中定義過了
QtUIforDesigner    moc_Plugin1.obj    1

這個錯誤基本上是因為在一個專案中,多次使用 Q_PLUGIN_METADATA 這個巨集產生的。

在 Qt 的 Plugin 系統中,Q_PLUGIN_METADATA 是用來定義專案是哪一種 plugin,所以在一個專案裡只能定義一次(官方文件)。

而如果希望在同一個專案裡面提供多個 Designer 的 plugin 的話,那就需要改用 plugin collection 的形式、透過單一個 plugin 的集合來統整所有 plugin 了。

以這邊是要撰寫 Qt Designer 的 plugin 來說,要使用的就是 QDesignerCustomWidgetCollectionInterface官方文件)。

他的介面相當簡單:

class QDesignerCustomWidgetCollectionInterface
{
public:
     virtual ~QDesignerCustomWidgetCollectionInterface() {}
     virtual QList<QDesignerCustomWidgetInterface*> customWidgets() const = 0; };

這邊要重新實作的,基本上就是透過 customWidgets() 這個函式,來回傳要使用的 QDesignerCustomWidgetInterface 了。

實際上寫的話,大概可以寫成下面的樣子:

#pragma once
#include "Plugin1.h"
#include "Plugin2.h"
#include <QtUiPlugin/QDesignerCustomWidgetCollectionInterface>
class MyCustomWidgets : public QObject, 
                        public QDesignerCustomWidgetCollectionInterface { Q_OBJECT Q_PLUGIN_METADATA(IID "org.qt-project.Qt.QDesignerCustomWidgetCollectionInterface") Q_INTERFACES(QDesignerCustomWidgetCollectionInterface) public: MyCustomWidgets(QObject* parent = 0) { m_vWidgets << new Plugin1(parent) << new Plugin2(parent); } QList<QDesignerCustomWidgetInterface*> customWidgets() const override { return m_vWidgets; } private: QList<QDesignerCustomWidgetInterface*> m_vWidgets; };

如此一來,MyCustomWidgets 這個 plugin collection 裡面,就會有 Plugin1Plugin1 這兩個 plugin 了。

而在 Plugin 的部分,也必須把定義中的 Q_PLUGIN_METADATA 拿掉,變成下面的形式:

class Plugin1 : public QObject, public QDesignerCustomWidgetInterface
{
  Q_OBJECT
  Q_INTERFACES(QDesignerCustomWidgetInterface)
  ...
}

經過這樣的修改,就可以把所有的 Qt Designer plugin 放到同一個專案下了。

而把這樣建置出來的 plugin DLL 檔拿到 Designer 用的話,在「說明」的「關於插件」視窗,就可以看到一個 dll 下有多個 Qt widget 了~


另外補充,在 Qt Designer 的 Plugin 中,其實在屬性、還有 signal / slot 的部分,也僅能使用基礎型別、還有一部分 QVariant 支援的型別(參考)。

自定義型別雖然可以使用,但是基本上應該是沒辦法帶到 Qt Designer 裡面用的;這點應該是系統面上的限制了。

Leave a Reply

發佈留言必須填寫的電子郵件地址不會公開。 必填欄位標示為 *