Qt项目开发遇到的问题4:在主程序中加载dll并显示出来,以及一些布局问题
先说一下布局的方式,一般来说不可能只添加一个dll,所以我们想办法将dll都显示出来的同时还可以美观方便;这里我的思路是用stackwidget将每个
dll都放在一个page中,添加一个dll创建相应的按钮,并将按钮绑定到相应的page中:
//初始显示第0页 ui->stackedWidget->setCurrentIndex(0); //这样可以让每次点击的时候都显示在第一页上
然后我们创建一个按钮:
先说明一下,mdlg是上一篇提到的,创建的一个 modulesmanager class
/模块加载配置对话框初始化 mdlg = NULL; //读取配置文件,需要加载哪些模块,已经模块的存放路径都存储于该文件中 LoadModulesFromCfg(); //信号槽匿名函数:创建并显示模块加载配置对话框 connect(ui->toolButton,&QToolButton::clicked,[=](){ if(mdlg == NULL)//当模块加载配置对话框未创建时,创建并建立信号槽机制 { mdlg = new ModulesManager(this); void(ModulesManager::*sig)(QString) = &ModulesManager::sigReLoadModule; void(MainWindow::*slot)(QString) = &MainWindow::slotReloadModule; connect(mdlg,sig,this,slot);//信号槽:当模块加载配置对话框发送重载信号时,主界面重载所有模块组件 //信号槽:当主界面发送刷新列表信号时,模块加载配置对话框刷新模块列表 connect(this,&MainWindow::sigRefreshTable,mdlg,&ModulesManager::slotRefressTableWidget); } mdlg->show(); });
来了来了他来了,添加删除的内容来了:
//模块加载 void MainWindow::slotReloadModule(QString path) { //加载模块 LoadModule(path); //发送刷新信号 emit sigRefreshTable(); } //卸载模块 void MainWindow::UnloadModule(QString &path) { if(m_mapModules.find(path) != m_mapModules.end()) { QMap<QString,QWidget*>::iterator itr = m_mapModulesWidget.find(path); if(itr != m_mapModulesWidget.end()) { itr.value()->setAttribute(Qt::WA_DeleteOnClose); itr.value()->close(); m_mapModulesWidget.remove(path); } QMap<QString,QAction*>::iterator itr2 = m_mapModulesActions.find(path); if(itr2 != m_mapModulesActions.end()) { ui->toolButton_5->removeAction(itr2.value()); m_mapModulesActions.remove(path); } if(m_mapModules[path]->unload()) { m_mapModules.remove(path); } } } //添加模块 int btnar = 1; QString MainWindow::LoadModule(QString &path) { QIcon* icon = NULL; QString* text = NULL; //若该模块已加载,则先卸载 UnloadModule(path); //动态加载共享库模块 QLibrary *lib = new QLibrary(path); if(lib->load()) { //将该模块储于模块列表 m_mapModules[path]= lib; // 解析符号 typedef QWidget* (*CreateFunc)(QWidget*); CreateFunc createDog = (CreateFunc)lib->resolve("CreateWidget"); int a1=btnar; QWidget *pa; switch (a1) { case 1: pa=ui->page; break; case 2: pa=ui->page_2; break; case 3: pa=ui->page_3; break; case 4: pa=ui->page_4; break; case 5: pa=ui->page_5; break; case 6: pa=ui->page_6; break; case 7: pa=ui->page_7; break; case 8: pa=ui->page_8; break; case 9: pa=ui->page_9; break; case 10: pa=ui->page_10; break; case 11: pa=ui->page_11; break; default: pa=ui->page_12; break; } if(createDog != NULL) { IModules* module = dynamic_cast<IModules*>(createDog(pa)); if (module) { icon = module->GetModuleIcon(); text = module->GetModuleText(); UDPSocket *udp = new UDPSocket(); module->setSysCtrl(udp); } } } else { qDebug() << lib->errorString(); return ""; } //添加启动按钮*icon,*text,this QToolButton *btn = new QToolButton(this); btn->setText(*text); btn->setIcon(*icon); btn->setToolButtonStyle(Qt::ToolButtonTextUnderIcon); btn->resize(150,80);//按钮大小 btn->setIconSize(QSize(100,50)); // //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// if(btnar<=6) { btn->move(btnar*150,80);//位置 } else { btn->move((btnar-6)*200,160);//位置 } btn->setStyleSheet("QToolButton{font-family:'幼圆';font-size:20px;color:rgb(115,45,0);}"); btn->setAutoRaise(true);//透明 //链接到每个page中。 int a=btnar; ui->stackedWidget->setCurrentIndex(0);//指定index0为初始界面 connect(btn,&QPushButton::clicked,[=](){ ui->stackedWidget->setCurrentIndex(a-1); }); btnar++; //信号槽:点击主界面启动按钮时,创建该模块的显示界面 connect(btn,&QPushButton::clicked,[=](){ //m_mapModulesWidget 该map用于存储已经创建了界面的“模块路径-模块显示界面” QMap<QString,QWidget*>::iterator itr = m_mapModulesWidget.find(path);//查找该模块显示界面是否被创建 if(itr != m_mapModulesWidget.end())//若该模块已经被创建,则无需创建,直接显示 { itr.value()->show(); } else //若该模块未创建,则需要创建该显示界面 { if(m_mapModules[path]!=NULL) { QLibrary* lib = m_mapModules[path];//在模块共享库map中取出该共享库调用实例 typedef QWidget* (*CreateFunc)(QWidget*); CreateFunc createDog = (CreateFunc)lib->resolve("CreateWidget"); if (createDog) {//创建并记录该共享库的“模块路径-模块显示界面” //pa指针指向page,以此将库内容显示到page上 QWidget *pa; switch (a) { case 1: pa=ui->page; break; case 2: pa=ui->page_2; break; case 3: pa=ui->page_3; break; case 4: pa=ui->page_4; break; case 5: pa=ui->page_5; break; case 6: pa=ui->page_6; break; case 7: pa=ui->page_7; break; case 8: pa=ui->page_8; break; case 9: pa=ui->page_9; break; case 10: pa=ui->page_10; break; case 11: pa=ui->page_11; break; default: pa=ui->page_12; break; } mWidget = createDog(pa); mWidget->show(); m_mapModulesWidget[path]= mWidget; } else {//若未实现该接口,则卸载该共享库模块 lib->unload(); } } else { qDebug() << lib->errorString(); } } }); //释放资源图片、文字资源 if(icon != NULL) { delete icon; } if(text != NULL) { delete text; } //返回模块的名称 return btn->text(); } void MainWindow::LoadModulesFromCfg() { //配置文件存放位置为运行目录跟目录下 QString pathFile = QCoreApplication::applicationDirPath() + "/Config.ini"; QSettings *configIniRead = new QSettings(pathFile, QSettings::IniFormat); //将读取到的ini文件保存在QString中,先取值,然后通过toString()函数转换成QString类型 configIniRead->setIniCodec("UTF8"); int count = configIniRead->value("num/count").toInt();//读取num下count的值,表示总共需要加载的模块数量 for (int i = 0; i < count ; i++) { //读取模块i共享库的存放路径 QString str = QString("module%1/path").arg(i+1); QString modulePath = configIniRead->value(str).toString(); //按照存放路径加载共享库 QString moduleName = LoadModule(modulePath); //如果共享库是新添加的,记录该模块的模块名称 if(moduleName!= "") { QSettings *configIniWrite = new QSettings(pathFile,QSettings::IniFormat); configIniWrite->setIniCodec("UTF8"); QString str = QString("module%1/name").arg(i+1); configIniWrite->setValue(str,moduleName); if(configIniWrite != NULL) delete configIniWrite; } } //读入入完成后删除指针 delete configIniRead; }
其中几个注意点,添加用到了dll中的函数,通过接口调用相关功能,加载dll的图标、路径、名字。
分配dll到相应的page中,这里没有动态创建page,而是采用了先创建12个page,如果有更好的方法欢迎补充。
这一篇先到这里吧,之后再介绍相关dll的功能和方法。

浙公网安备 33010602011771号