近来学习QT的插件框架,记录一些心得
1、插件的好处:
基于插件的设计好处很多,把扩展功能从框架中剥离出来,降低了框架的复杂度,让框架更容易实现.扩展功能与框架以一种很松的方式耦合,两者在保持接口不变的情况下,可以独立变化和发布,将软件的复杂度限制在了单个的插件之中,比较适用与需求不定或是业务容易发生变化的软件设计.
2、构建插件框架
2.1主程序
2.1.1接口
//step 1 定义接口
class MainInterface
{
public:
virtual ~MainInterface(){}
virtual QString name() = 0;
virtual QString information() = 0;
//返回一个Widget设置到centerwidget中进行显示
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 返回插件的个数
*/
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 根据插件生成menu
* @param pluginInterface 插件
* @param i 插件实现的接口
*/
void MainWindow::populateMenus(QObject * pluginInterface,MainInterface*i )
{
static auto menu = menuBar()->addMenu("widgets");
auto act = new QAction(i->name(),pluginInterface);
//单击menu调用插件
connect(act,&QAction::triggered,this,&MainWindow::slt_WidgetActionTriggered);
menu->addAction(act);
}
/**
* @brief MainWindow::slt_WidgetActionTriggered 单击menu调用插件
*/
void MainWindow::slt_WidgetActionTriggered()
{
auto centerWidget = qobject_cast<MainInterface*>(sender()->parent())->centerWidget();
setCentralWidget(centerWidget);
}
2.2 接口实现
class CENTERWIDGETTWOSHARED_EXPORT CenterWidgetTwo
:public QObject
,public MainInterface
{
Q_OBJECT
//Q_INTERFACES 宏用于告诉 Qt 该类实现的接口。
Q_INTERFACES(MainInterface)
//Q_PLUGIN_METADATA宏用于描述插件元数据
Q_PLUGIN_METADATA(IID MainInterface_iid)
public:
CenterWidgetTwo();
~CenterWidgetTwo();
//实现虚函数
virtual QString name() override;
virtual QString information() override;
virtual QWidget *centerWidget() override;
};
QWidget *CenterWidgetTwo::centerWidget()
{
auto btn = new QPushButton("Two");
return btn;
}
程序截图
加载界面1
加载界面2