إنشاء نظام ملحق على مكتبة Qt

ملحقات (ملحقات)


الإضافات هي مكتبة ديناميكية مشتركة مصممة ليتم تحميلها أثناء تنفيذ التطبيق الرئيسي ، والتي يجب أن تنفذ بالضرورة واجهة خاصة واحدة على الأقل.

يتم تقسيم الامتدادات إلى نوعين:

  • للحصول على كيو تي
  • للتطبيقات الأصلية

دعنا نتعرف على كيفية إنشاء نظام الإضافات الخاص بك والإضافات الخاصة به.

يتم التواصل مع الامتداد باستخدام الواجهة (إشارات ، فتحات وأساليب الفصل). يتم تحميل الملحق بواسطة التطبيق باستخدام فئة QPluginLoader . لتحميل الملحق ، يتم استخدام أسلوب مثيل () ، والذي ينشئ كائن ملحق ويقوم بإرجاع مؤشر إليه. يتم استخدام طريقة unload () لتفريغ الملحق.

الجزء 1


في المثال الأول ، قم بإنشاء ملحق يستخدم دالة (الخوارزمية ، الصيغة) من الملحق.

المخطط البصري للمشروع سيبدو كما يلي.



المرحلة 1:


تتمثل الخطوة الأولى في إنشاء فئة واجهة موروثة من QObject ، حيث سيكون هناك واجهة تأخذ متغيراً من النوع QString وتُرجع السلسلة نفسها في الحالة العليا. باستخدام الماكرو Q_DECLARE_INTERFACE ، قمنا بتعيين معرف الواجهات ، ويقوم المترجم c بإنشاء معلومات التعريف لسلسلة المعرف. هذه الوحدة هي بروتوكول الاتصال بين البرنامج المساعد والبرنامج الرئيسي وسيتم استخدامه في مشروع البرنامج المساعد والمشروع الرئيسي.

سيبدو الفصل على النحو التالي.

//--------------------------------------------------- #ifndef INTERFACE_H #define INTERFACE_H //------------------------------------------------------- #include <QObject> //------------------------------------------------------- class interface : public QObject { public: /// \brief   virtual ~interface() = default; /// \brief   virtual QString getUpString(QString str) = 0; }; //---------------------------------------------------------------- Q_DECLARE_INTERFACE(interface, "com.mysoft.Application.interface") //---------------------------------------------------------------- #endif // INTERFACE_H //---------------------------------------------------------------- 


المرحلة 2:


لنقم بإنشاء تطبيق أساسي لتنزيل الامتداد. بالضغط على الزر ، سيتم البحث عن الامتداد وتحميله في النظام. كذلك من خلال الواجهة سوف نستخدم وظيفتنا.

التطبيق الأساسي:

mainproject.h

 //--------------------------------------------------- #ifndef MAINPROJECT_H #define MAINPROJECT_H //------------------------------------------------------- #include <QWidget> #include <QPluginLoader> #include <QDir> #include "interface.h" //------------------------------------------------------- namespace Ui { class mainProject; } //------------------------------------------------------- class mainProject : public QWidget { Q_OBJECT public: /// \brief  explicit mainProject(QWidget *parent = nullptr); /// \brief  ~mainProject(); private slots: /// \brief   void on_searchPlugin_clicked(); /// \brief   void on_getUp_clicked(); private: Ui::mainProject *ui; interface *pluginObject; ///<     }; //------------------------------------------------------- #endif // MAINPROJECT_H //------------------------------------------------------- 

mainproject.cpp

 //--------------------------------------------------- #include "mainproject.h" #include "ui_mainproject.h" //------------------------------------------------------- mainProject::mainProject(QWidget *parent) : QWidget(parent), ui(new Ui::mainProject) { ui->setupUi(this); } //------------------------------------------------------- mainProject::~mainProject() { delete ui; } //------------------------------------------------------- void mainProject::on_searchPlugin_clicked() { QStringList listFiles; QDir dir(QApplication::applicationDirPath() + "/Plugins/"); //      "Plugins" if(dir.exists()) listFiles = dir.entryList(QStringList("*"), QDir::Files); //     for(QString str: listFiles) { QPluginLoader loader(dir.absolutePath() + "/" +str); QObject *pobj = 0; //   pobj = qobject_cast<QObject*>(loader.instance()); if(!pobj) continue; pluginObject = 0; //   pluginObject = qobject_cast<interface *>(pobj); //      if(pluginObject) { ui->label->setText(" "); break; } } } //------------------------------------------------------- void mainProject::on_getUp_clicked() { QString tmp; tmp = ui->lineEdit->text(); //   getUpString() tmp = pluginObject->getUpString(tmp); ui->label_2->setText(tmp); } //------------------------------------------------------- 


المرحلة 3:


عند إنشاء ملحق ، فإن أول ما يجب فعله هو تغيير نوع المشروع الذي تم إنشاؤه في الملف pro ، لذلك تحتاج إلى إضافة السطر التالي TEMPLATE = lib ، وتعيين تكوين المشروع لملحق CONFIG + = plugin.

upperstringplugin.pro

 #------------------------------------------------- # # Project created by QtCreator 2019-04-03T11:35:18 # #------------------------------------------------- QT += core greaterThan(QT_MAJOR_VERSION, 4): QT += widgets TARGET = upperStringPlugin TEMPLATE = lib CONFIG += plugin DESTDIR = ../Plugins DEFINES += QT_DEPRECATED_WARNINGS CONFIG += c++11 SOURCES += \ upperstringplugin.cpp HEADERS += \ upperstringplugin.h \ interface.h 

بعد ذلك ، نقوم بإنشاء فصل للامتداد المستقبلي ، يجب أن يتم وراثة الفئة من فئة الواجهات. ماكرو Q_INTERFACES ، تحتاج إلى برنامج التحويل البرمجي لإنشاء كافة معلومات التعريف الضرورية للملحق . يعين الماكرو Q_PLUGIN_METADATA () نقطة الإدخال إلى الملحق والوصول إلى مكتبة Qt. تحتاج أيضًا إلى إنشاء ملف inteface.json مع معلومات التعريف (يجب أن يكون الملف في جذر المشروع) ، وفي حالتنا لا توجد معلومات هناك ، لذلك اكتب علامات اقتباس فارغة {} في الملف.

upperstringplugin.h

 //--------------------------------------------------- #ifndef UPPERSTRINGPLUGIN_H #define UPPERSTRINGPLUGIN_H //--------------------------------------------------- #include "interface.h" //--------------------------------------------------- class upperStringPlugin : public interface { Q_OBJECT Q_INTERFACES(interface) Q_PLUGIN_METADATA(IID "com.mysoft.Application.interface" FILE "interface.json") public: explicit upperStringPlugin(); ~upperStringPlugin(); // interface interface public: QString getUpString(QString str); }; //--------------------------------------------------- #endif // UPPERSTRINGPLUGIN_H //--------------------------------------------------- 

upperstringplugin.cpp

 //--------------------------------------------------- #include "upperstringplugin.h" //--------------------------------------------------- upperStringPlugin::upperStringPlugin() {} //--------------------------------------------------- upperStringPlugin::~upperStringPlugin() {} //--------------------------------------------------- QString upperStringPlugin::getUpString(QString str) { return str.toUpper(); } //--------------------------------------------------- 

عند إخراج ترجمة المشروع ، نحصل على ملف بالملحق. لذا ، ننقل هذا الملف إلى مجلد الإضافات الخاص بالمشروع الرئيسي ، ونبدأ تشغيله. في هذه الحالة ، يتم تحميل الملحق في البرنامج الرئيسي ويتم إنشاء كائن ملحق واحد. إذا حاولت إعادة استخدام وظيفة مثيل () ، فستقوم الدالة بإرجاع مؤشر إلى كائن الملحق الذي تم إنشاؤه بالفعل.

تنفيذ البرنامج



الجزء 2


لتعقيد مهمتنا ، نحتاج الآن إلى أن تكون الإضافة أداة مصغّرة وقدرة على إنشاء العديد من هذه الأدوات المصغّرة. سيتلقى البرنامج الرئيسي رسائل من الإضافات ويرسل ردًا. سننشئ مشروعات جديدة ، في المرحلة الأولى ، سنحتاج إلى فئتين من الواجهات ، أحدهما سيكون مسؤولاً عن تحميل الامتداد وإنشاء الأداة ، والآخر لتشغيل الأداة نفسها.

سيبدو مخطط المشروع كما يلي:



المرحلة 1:


سيكون لواجهة الواجهة الأولى وظيفتان ، الحصول على اسم البرنامج المساعد والحصول على عنصر واجهة المستخدم المساعد. سيتم تخزين اسم البرنامج المساعد لتحديد الهوية في النظام. سنضيف عنصر واجهة المستخدم المساعد إلى نوافذ MDI للتطبيق الرئيسي.

الفئة الثانية هي القطعة الرسومية نفسها ، فهي موروثة من QWidget ، وهنا حددنا الوظائف التي نحتاجها ، وسوف تتلقى القطعة رسالة وإرسالها إلى البرنامج الرئيسي.

interface.h

 //------------------------------------------------------------------------- #ifndef INTERFACE_H #define INTERFACE_H //------------------------------------------------------------------------- #include <QWidget> class QString; //------------------------------------------------------------------------- class interface : public QObject { public: /// \brief  virtual ~interface(){} /// \brief    virtual QString getNamePlugin() = 0; /// \brief    virtual QObject *getPluginWidget() = 0; }; //------------------------------------------------------------------------- class interfaceWidget: public QWidget { public: /// \brief  virtual ~interfaceWidget() = default; signals: /// \brief      virtual void signal_writeText(QString str) = 0; public slots: /// \brief      virtual void slot_getText(QString str) = 0; }; //------------------------------------------------------------------------- Q_DECLARE_INTERFACE(interface, "com.mysoft.Application.interface") //------------------------------------------------------------------------- #endif // INTERFACE_H //------------------------------------------------------------------------- 

المرحلة 2:


يتكون البرنامج الرئيسي من نافذة MDI ، حيث يوجد عنصر واجهة رئيسية لتلقي الرسائل من الإضافات والنوافذ الإضافية التي تظهر ديناميكيًا كما تسمى الإضافات.

عند إنشاء عنصر واجهة مستخدم إضافي ، نقوم بتوصيل الإشارة من المكون الإضافي إلى الفتحة وباستخدام وظيفة المرسل () نحصل على مؤشر إلى المكون الإضافي الذي أرسل الرسالة. نضع عنصر واجهة المستخدم الذي تم إنشاؤه في نافذة MDI ، ويمكن إلغاء تحميل كائن المكون الإضافي نفسه من النظام.

mainproject.h

 //------------------------------------------------ #ifndef MAINPROJECT_H #define MAINPROJECT_H //------------------------------------------------ #include <QMainWindow> #include <QDir> #include <QPluginLoader> #include "interface.h" //------------------------------------------------ namespace Ui { class mainProject; } //------------------------------------------------ typedef struct str_plugin { QString namePlugin; ///<   QString dirPlugin; ///<   }TSTR_PLUGIN; //------------------------------------------------ class mainWidget; //------------------------------------------------ class mainProject : public QMainWindow { Q_OBJECT public: explicit mainProject(QWidget *parent = nullptr); ~mainProject(); private slots: void on_action_triggered(); /// \brief    void slot_showPlugin(); /// \brief          void slot_getTextFromPlugin(QString str); private: Ui::mainProject *ui; mainWidget *widget; ///<   QVector<TSTR_PLUGIN > vecPlugin; ///<   }; //------------------------------------------------ #endif // MAINPROJECT_H //------------------------------------------------ 

mainproject.cpp

 //------------------------------------------------ #include "mainproject.h" #include "ui_mainproject.h" #include "mainwidget.h" #include <QMdiSubWindow> //------------------------------------------------ mainProject::mainProject(QWidget *parent) : QMainWindow(parent), ui(new Ui::mainProject) { ui->setupUi(this); QMdiSubWindow *sWPS = new QMdiSubWindow; widget = new mainWidget(); sWPS->setWidget(widget); ui->mdiArea->addSubWindow(sWPS); } //------------------------------------------------ mainProject::~mainProject() { delete ui; } //------------------------------------------------ void mainProject::on_action_triggered() { ui->menu_2->clear(); QStringList listFiles; QDir dir(QApplication::applicationDirPath() + "/Plugins/"); if(dir.exists()) { listFiles = dir.entryList(QStringList("*"), QDir::Files); } for(QString str: listFiles) { QPluginLoader loader(dir.absolutePath() + "/" +str); QObject *pobj = 0; pobj = qobject_cast<QObject*>(loader.instance()); if(!pobj) continue; interface *plW = 0; plW = qobject_cast<interface *>(pobj); if(!plW) continue; QString namePlugin = plW->getNamePlugin(); QAction *action = new QAction(namePlugin); ui->menu_2->addAction(action); connect(action, SIGNAL(triggered()), this, SLOT(slot_showPlugin())); TSTR_PLUGIN plug; plug.namePlugin = namePlugin; plug.dirPlugin = dir.absolutePath() + "/" +str; vecPlugin.push_back(plug); delete plW; } } //------------------------------------------------ void mainProject::slot_showPlugin() { QObject *pobj = sender(); QAction *action = qobject_cast<QAction *>(pobj); QString namePlugin = action->iconText(); for(int i = 0; i < vecPlugin.size(); i++) { if(namePlugin == vecPlugin[i].namePlugin) { QMdiSubWindow *sWPS = new QMdiSubWindow; ui->mdiArea->addSubWindow(sWPS); sWPS->setAttribute(Qt::WA_DeleteOnClose, true); QPluginLoader loader(vecPlugin[i].dirPlugin); QObject *pobj = qobject_cast<QObject*>(loader.instance()); if(!pobj) continue; interface *plW = qobject_cast<interface *>(pobj); if(!plW) continue; QObject *ob = plW->getPluginWidget(); if(!ob) continue; interfaceWidget *interFaceW = dynamic_cast<interfaceWidget *>(ob); if(!interFaceW) continue; sWPS->setWidget(interFaceW); sWPS->show(); QSize size = interFaceW->minimumSize(); size.setHeight(size.height() + 20); size.setWidth(size.width() + 20); sWPS->resize(size); loader.unload(); connect(interFaceW, SIGNAL(signal_writeText(QString)), this, SLOT(slot_getTextFromPlugin(QString))); } } } //------------------------------------------------ void mainProject::slot_getTextFromPlugin(QString str) { //     QObject *pobj = sender(); interfaceWidget *pPlug = dynamic_cast<interfaceWidget *>(pobj); widget->slot_getText("   "); widget→slot_getText(str); widget->slot_getText(" "); widget→slot_getText("------------------------------"); pPlug->slot_getText(" "); } //------------------------------------------------ 

النافذة الرئيسية تقبل الرسالة وتعرضها.

mainwidget.h

 //---------------------------------------------------------- #ifndef MAINWIDGET_H #define MAINWIDGET_H //---------------------------------------------------------- #include <QWidget> //---------------------------------------------------------- namespace Ui { class mainWidget; } //---------------------------------------------------------- class mainWidget : public QWidget { Q_OBJECT public: explicit mainWidget(QWidget *parent = nullptr); ~mainWidget(); public slots: /// \brief      void slot_getText(QString str); private: Ui::mainWidget *ui; }; //---------------------------------------------------------- #endif // MAINWIDGET_H //---------------------------------------------------------- 

mainwidget.cpp

 //---------------------------------------------------------- #include "mainwidget.h" #include "ui_mainwidget.h" //---------------------------------------------------------- mainWidget::mainWidget(QWidget *parent) : QWidget(parent), ui(new Ui::mainWidget) { ui->setupUi(this); } //---------------------------------------------------------- mainWidget::~mainWidget() { delete ui; } //---------------------------------------------------------- void mainWidget::slot_getText(QString str) { ui->textEdit->append(str); } //---------------------------------------------------------- 

المرحلة 2:


نقوم بإنشاء مكون إضافي ، فكرته هي أنه مصنع لإنشاء عنصر واجهة مستخدم.

plugin.h

 //------------------------------------------------- #ifndef PLUGIN_H #define PLUGIN_H //------------------------------------------------- #include "interface.h" #include "texttranferwidget.h" //------------------------------------------------- class plugin : public interface { Q_OBJECT Q_INTERFACES(interface) Q_PLUGIN_METADATA(IID "com.mysoft.Application.interface" FILE "interface.json") public: explicit plugin(); ~plugin(); // interface interface public: /// \brief    QString getNamePlugin(); /// \brief    QObject *getPluginWidget(); }; //------------------------------------------------- #endif // PLUGIN_H //------------------------------------------------- 

plugin.cpp

 //------------------------------------------------- #include "plugin.h" //------------------------------------------------- plugin::plugin() { } //------------------------------------------------- plugin::~plugin() { } //------------------------------------------------- QString plugin::getNamePlugin() { return " 1"; } //------------------------------------------------- QObject *plugin::getPluginWidget() { textTranferWidget *widget = new textTranferWidget(); return qobject_cast<QObject *>(widget); } //------------------------------------------------- 

القطعة التي أنشأتها البرنامج المساعد.

texttranferwidget.h

 //------------------------------------------------------------------- #ifndef TEXTTRANFERWIDGET_H #define TEXTTRANFERWIDGET_H //------------------------------------------------------------------- #include "interface.h" //------------------------------------------------------------------- namespace Ui { class textTranferWidget; } //------------------------------------------------------------------- class textTranferWidget : public interfaceWidget { Q_OBJECT public: /// \brief  explicit textTranferWidget(); /// \brief  ~textTranferWidget(); private: Ui::textTranferWidget *ui; // interfaceWidget interface signals: /// \brief      void signal_writeText(QString str); public slots: /// \brief      void slot_getText(QString str); private slots: void on_pushButton_clicked(); }; //------------------------------------------------------------------- #endif // TEXTTRANFERWIDGET_H //------------------------------------------------------------------- 

texttranferwidget.cpp

 //------------------------------------------------------------------- #include "texttranferwidget.h" #include "ui_texttranferwidget.h" //------------------------------------------------------------------- textTranferWidget::textTranferWidget() : ui(new Ui::textTranferWidget) { ui->setupUi(this); } //------------------------------------------------------------------- textTranferWidget::~textTranferWidget() { delete ui; } //------------------------------------------------------------------- void textTranferWidget::slot_getText(QString str) { ui->textEdit->append(str); } //------------------------------------------------------------------- void textTranferWidget::on_pushButton_clicked() { emit signal_writeText(ui->lineEdit->text()); } //------------------------------------------------------------------- 

مخرجات البرنامج الرئيسي:

Source: https://habr.com/ru/post/ar448806/


All Articles