QT custom control plug-in learning notes

Posted by carlg on Mon, 03 Jan 2022 02:21:29 +0100

This paper mainly expounds the creation and calling methods and precautions of custom control plug-in.

catalogue

1, Create a custom control plug-in

1. Qt Designer special interface

2. Custom control class interface of plug-in

2, Calling a custom control plug-in

1. Dynamic call plug-in

2. Static call plug-in

3, Conclusion

1, Create a custom control plug-in

1. Qt Designer special interface

1.1. Control collector interface

Base class: QDesignerCustomWidgetCollectionInterface

Purpose: load all custom control classes into a QList

#pragma once
#include <QtDesigner>
#include <qplugin.h>
​
class WidgetCollectionInterface : public QObject, public QDesignerCustomWidgetCollectionInterface
{
    Q_OBJECT
    Q_INTERFACES(QDesignerCustomWidgetCollectionInterface)  
#if QT_VERSION >= 0x050000
    Q_PLUGIN_METADATA(IID "org.qt-project.Qt.QDesignerCustomWidgetCollectionInterface")
#endif // QT_VERSION >= 0x050000
​
public:
    WidgetCollectionInterface(QObject* parent = 0);
​
    QList<QDesignerCustomWidgetInterface*> customWidgets() const override;
​
private:
    QList<QDesignerCustomWidgetInterface*> widgets;
};

Key points:

Two macros that declare a unique interface

Q_INTERFACES(QDesignerCustomWidgetCollectionInterface) 
Q_PLUGIN_METADATA(IID "org.qt-project.Qt.QDesignerCustomWidgetCollectionInterface")

Constructor to load all custom control classes

WidgetCollectionInterface::WidgetCollectionInterface(QObject* parent)
    : QObject(parent)
{
    widgets.append(new MyProgressBar1Interface(this));
    //widgets.append(new CustomWidgetTwoInterface(this));
    //widgets.append(new CustomWidgetThreeInterface(this));
}

1.2. Single custom control interface

Base class: QDesignerCustomWidgetInterface

Purpose: to define the information of a single custom control by rewriting the virtual function, so that Qt Designer can load the information of the custom control through dll Dynamic call,

Its information includes control icon, control name, control header file, control group name, control class name, default name of object instance automatically generated by Qt Designer drag, etc

#pragma once
​
#include <QtUiPlugin/QDesignerCustomWidgetInterface>
#include <QtDesigner/QtDesigner>
class MyProgressBar1Interface : public QObject, public QDesignerCustomWidgetInterface
{
    Q_OBJECT
    Q_INTERFACES(QDesignerCustomWidgetInterface)
​
public:
    MyProgressBar1Interface(QObject *parent = Q_NULLPTR);
​
    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;
};

Key points:

Virtual function override of base class QDesignerCustomWidgetInterface

#include <QtUiPlugin/QDesignerCustomWidgetInterface>
#include <QtDesigner/QtDesigner>
class MyProgressBar1Interface : public QObject, public QDesignerCustomWidgetInterface
{
    Q_OBJECT
    Q_INTERFACES(QDesignerCustomWidgetInterface)
    ...    
    ...
    ...
}

2. Custom control class interface of plug-in

2.1. Implementation of custom controls

Control inherits the base class, control properties, control drawing, signal / slot, event and other conventional custom control implementations. Refer to the use of QPainter for details

#pragma once
#include <QProgressBar>
#include <QFont>
#include <QColor>
#include <QBrush>
#include <QPen>
​
#include <QtDesigner/QtDesigner>
​
class QDESIGNER_WIDGET_EXPORT MyProgressBar1 :
    public QProgressBar
{
    Q_OBJECT
    Q_PROPERTY(QFont textFont READ getTextFont WRITE setTextFont)
    Q_PROPERTY(QColor textColor READ getTextColor WRITE setTextColor)
    Q_PROPERTY(QPen circleLinePen READ getCircleLinePen WRITE setCircleLinePen)
    Q_PROPERTY(QBrush barBackgroundBrush READ getBarBackgroundBrush WRITE setBarBackgroundBrush)
    Q_PROPERTY(QBrush barForegroundBrush READ getBarForegroundBrush WRITE setBarForegroundBrush)
​
public:
    explicit MyProgressBar1(QWidget* parent = nullptr);
    virtual ~MyProgressBar1();
​
protected:
    virtual void paintEvent(QPaintEvent* event);
​
public:
    QFont getTextFont() const;
    void setTextFont(const QFont& font);
    QColor getTextColor() const;
    void setTextColor(const QColor& color);
    QPen getCircleLinePen() const;
    void setCircleLinePen(const QPen& pen);
    QBrush getBarBackgroundBrush() const;
    void setBarBackgroundBrush(const QBrush& brush);
    QBrush getBarForegroundBrush() const;
    void setBarForegroundBrush(const QBrush& brush);
​
private:
    QFont textFont; //Font format
    QColor textColor; //Font color
    QPen circleLinePen; //Circle outline brush
    QBrush barBackgroundBrush; //Progress bar background brush
    QBrush barForegroundBrush; //Progress bar brush
​
private:
    void InitUi();
    void TestPainter();
};
​

2.2 class interface export

  • Using QDESIGNER_WIDGET_EXPORT declaration class. The header file of this macro is #include < qtdesigner / qtdesigner >
#include <QtDesigner/QtDesigner>
​
class QDESIGNER_WIDGET_EXPORT MyProgressBar1 : public QProgressBar
  • Predefined macro QDESIGNER_EXPORT_WIDGETS

    This macro is defined as follows, so be sure to predefine the macro QDESIGNER_EXPORT_WIDGETS to enable it to export interfaces, otherwise But dll is compiled.

#if defined(QDESIGNER_EXPORT_WIDGETS)
#  define QDESIGNER_WIDGET_EXPORT __declspec(dllexport)
#else
#  define QDESIGNER_WIDGET_EXPORT __declspec(dllimport)
#endif

2, Calling a custom control plug-in

1. Dynamic call plug-in

Implementation principle: mainly through dll project to implement WidgetCollectionInterface, MyProgressBar1Interface and other classes. First load all custom control classes into WidgetCollection, then export the custom class through name() when calling, and then createWidget().

Purpose: to enable Qt Designer to load all the controls in the custom control plug-in at one time, so that users can directly use the controls by dragging and dropping

Special note: this calling method cannot directly new the custom control class. You can only call the member function of the custom control class through the following methods (LoadInterface, CreateCustomWidget)

bool CustomWidgetTestDemo::LoadInterface(QString pluginName)
{
    QFileInfo pluginFile( QString("%1/%2").arg(QCoreApplication::applicationDirPath()).arg(pluginName));
    QString pluginFilePath = pluginFile.absoluteFilePath();
    QPluginLoader load(pluginFilePath);
    QObject* obj = load.instance(); //Load dll
    if (obj != nullptr)
    {
        m_interface = qobject_cast<CustomWidgetCollectionInterface*>(obj);  //Load interface
        if (m_interface != nullptr)
        {
            return true;
        }
        else
        {
            QMessageBox::critical(this, "ERROR", QString::fromStdWString(L"CustomWidgetCollectionInterface Loading failed!"));
        }
    }
    else
    {
        QMessageBox::critical(this, "ERROR", QString::fromStdWString(L"<%1>Loading failed!").arg(pluginFilePath));
    }
    return false;
}
​
template<class T>
T* CustomWidgetTestDemo::CreateCustomWidget(QString name, QWidget* parent)
{
    QList<QDesignerCustomWidgetInterface*> widgets = m_interface->customWidgets();
    for each (QDesignerCustomWidgetInterface * var in widgets)
    {
        if (var->name() == name)
        {
            T* widget;
            widget = static_cast<T*>(var->createWidget(parent));
            if (widget != nullptr)
            {
                return widget;
            }
            break;
        }
    }
    QMessageBox::critical(this, "ERROR", QString::fromStdWString(L"Custom control<%1>Loading failed!").arg(name));
    return nullptr;
}
​
LoadInterface("QtCustomYihPlugin.dll");
MyProgressBar1* myProgressBar1 = CreateCustomWidget<MyProgressBar1>("MyProgressBar1", this);
myProgressBar1->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Preferred);

 

2. Static call plug-in

Implementation principle: mainly through Add qdesigner before the custom control class in dll project_ WIDGET_ Export. Actually, it's for you dll definition class interface

Purpose: to instantiate the custom control class, that is, the new custom control object The source code generated by the ui file is also used to instantiate the custom control through new, which is similar to the following code.

Special note: with static calls dll method, which needs to be set lib dependency and its path

MyProgressBar1* myProgressBar1_666;
myProgressBar1_666 = new MyProgressBar1(this);
myProgressBar1_666->setObjectName(QString::fromUtf8("myProgressBar1_1"));
myProgressBar1_666->setGeometry(QRect(320, 60, 271, 191));
myProgressBar1_666->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Preferred);
m_Layout->addWidget(myProgressBar1_666);

3, Conclusion

For information about the production of custom controls and the complete steps of calling control plug-ins, you can refer to the following materials:

Internet blog: < QT writing custom control plug-ins, passing pits and precautions >

Internet blog: < QT for Qt Designer >

Books: < QT creator quick start_ Third edition >

Demo source code (JaneYih PC):

Solution name: CustomWidgetProject

Create plug-in project name: QtCustomYihPlugin

Call plug-in project name: CustomWidgetTestDemo

 

Reprint please indicate the source!!

If there is any mistake, please give advice~

Topics: Qt