近來(lái)學(xué)習(xí)QT的插件框架辕棚,記錄一些心得
1符欠、插件的好處:
基于插件的設(shè)計(jì)好處很多,把擴(kuò)展功能從框架中剝離出來(lái),降低了框架的復(fù)雜度,讓框架更容易實(shí)現(xiàn).擴(kuò)展功能與框架以一種很松的方式耦合,兩者在保持接口不變的情況下,可以獨(dú)立變化和發(fā)布,將軟件的復(fù)雜度限制在了單個(gè)的插件之中,比較適用與需求不定或是業(yè)務(wù)容易發(fā)生變化的軟件設(shè)計(jì).
2夏块、構(gòu)建插件框架
2.1主程序
2.1.1接口
//step 1 定義接口
class MainInterface
{
public:
virtual ~MainInterface(){}
virtual QString name() = 0;
virtual QString information() = 0;
//返回一個(gè)Widget設(shè)置到centerwidget中進(jìn)行顯示
virtual QWidget *centerWidget() = 0;
};
//step 2 聲明接口
#define MainInterface_iid "com.Interface.MainInterface"
Q_DECLARE_INTERFACE(MainInterface, MainInterface_iid)
2.1.2 主程序加載接口
/**
* @brief MainWindow::loadPlugins 加載插件蠢护、插件放在plugins文件夾下
* @return 返回插件的個(gè)數(shù)
*/
int MainWindow::loadPlugins()
{
int count = 0;
QDir pluginsDir = QDir(qApp->applicationDirPath());
if(!pluginsDir.cd("plugins")) return -1;
foreach (QString fileName, pluginsDir.entryList(QDir::Files))
{
QPluginLoader pluginLoader(pluginsDir.absoluteFilePath(fileName));
QObject *plugin = pluginLoader.instance();
if(plugin)
{
auto centerInterface = qobject_cast<MainInterface*>(plugin);
if(centerInterface)
{
++count;
//加載插件后生成menu
populateMenus(plugin,centerInterface);
}
}
}
return count;
}
/**
* @brief MainWindow::populateMenus 根據(jù)插件生成menu
* @param pluginInterface 插件
* @param i 插件實(shí)現(xiàn)的接口
*/
void MainWindow::populateMenus(QObject * pluginInterface,MainInterface*i )
{
static auto menu = menuBar()->addMenu("widgets");
auto act = new QAction(i->name(),pluginInterface);
//單擊menu調(diào)用插件
connect(act,&QAction::triggered,this,&MainWindow::slt_WidgetActionTriggered);
menu->addAction(act);
}
/**
* @brief MainWindow::slt_WidgetActionTriggered 單擊menu調(diào)用插件
*/
void MainWindow::slt_WidgetActionTriggered()
{
auto centerWidget = qobject_cast<MainInterface*>(sender()->parent())->centerWidget();
setCentralWidget(centerWidget);
}
2.2 接口實(shí)現(xiàn)
class CENTERWIDGETTWOSHARED_EXPORT CenterWidgetTwo
:public QObject
,public MainInterface
{
Q_OBJECT
//Q_INTERFACES 宏用于告訴 Qt 該類(lèi)實(shí)現(xiàn)的接口惕蹄。
Q_INTERFACES(MainInterface)
//Q_PLUGIN_METADATA宏用于描述插件元數(shù)據(jù)
Q_PLUGIN_METADATA(IID MainInterface_iid)
public:
CenterWidgetTwo();
~CenterWidgetTwo();
//實(shí)現(xiàn)虛函數(shù)
virtual QString name() override;
virtual QString information() override;
virtual QWidget *centerWidget() override;
};
QWidget *CenterWidgetTwo::centerWidget()
{
auto btn = new QPushButton("Two");
return btn;
}
程序截圖
加載界面1
加載界面2