CTK框架 - 将菜单按钮写到插件中

news/2024/11/28 11:55:19/

文章目录

  • CTK框架 - 将菜单按钮写到插件中
    • 代码示例
    • 之前关闭的时候崩溃错误

CTK框架 - 将菜单按钮写到插件中

之前我们在的两个插件Core和About,在Core和About中加入了界面,并且Core中插入了一个菜单,点击之后弹出About界面。

我们现在来用之前的知识把菜单改成注册的,并且点击之后弹出About界面。

我这里的思路是使用事件或者是在Core中加注册的服务来注册菜单。之后点击菜单的时候发送事件。

代码示例

  1. 编写一个menubar 用来管理菜单和处理其他插件注册的menu事件

menubar.h

#ifndef CTKPLUGIN_MENUBAR_H
#define CTKPLUGIN_MENUBAR_H
#include <QMenuBar>
#include "service/event/ctkEventAdmin.h"
#include "service/event/ctkEventHandler.h"
class MenuBar : public QMenuBar, public ctkEventHandler
{Q_OBJECTQ_INTERFACES(ctkEventHandler)
public:MenuBar(ctkPluginContext *context, QWidget *parent = nullptr);~MenuBar() override;void initMenu();QMenu *getMenu(const QString &name);
signals:void sig_insertMenu(const QJsonObject &obj);
protected:void handleEvent(const ctkEvent& event) override;
protected slots:void insertMenuAndActions(const QJsonObject &obj);void actionTriggered();
private:ctkPluginContext *context_;QStringList menu_descriptions_;QMap<QString, QMenu*> menu_map_;QMap<QString, QList<QAction *>> actions_map_;
};#endif //CTKPLUGIN_MENUBAR_H

menubar.cpp

#include "menubar.h"
#include "ctkPluginContext.h"
#include "service/event/ctkEventConstants.h"
#include <iostream>
#include <QJsonObject>
#include <QJsonDocument>
#include <QAction>
MenuBar::MenuBar(ctkPluginContext *context, QWidget *parent): QMenuBar(parent), context_(context)
{menu_descriptions_ << "File" << "Edit" << "MPI" << "Help" << "Page";initMenu();connect(this, &MenuBar::sig_insertMenu, this, &MenuBar::insertMenuAndActions, Qt::QueuedConnection);// 注册监听信号"mainwindow_action"ctkDictionary dic;dic.insert(ctkEventConstants::EVENT_TOPIC, "mainwindow_action");try {context_->registerService<ctkEventHandler>(this, dic);}catch (ctkException e){std::cout << e.message().toStdString() << std::endl;}
}
MenuBar::~MenuBar()
{
}
void MenuBar::initMenu()
{for(const auto &name : menu_descriptions_){QMenu *menu = new QMenu(name,this);menu_map_[name] = menu;addMenu(menu);}
}
void MenuBar::handleEvent(const ctkEvent &event)
{if(event.getTopic() == "mainwindow_action"){QStringList names  = event.getPropertyNames();for(const auto &name : names){QVariant val = event.getProperty(name);emit sig_insertMenu(val.toJsonObject());}}
}
void MenuBar::actionTriggered()
{QAction *action = dynamic_cast<QAction *>(sender());QString text = action->text();std::cout << text.toStdString() << std::endl;//获取事件服务接口ctkServiceReference ref;ctkEventAdmin* eventAdmin{nullptr};ref = context_->getServiceReference<ctkEventAdmin>();if(ref){eventAdmin = context_->getService<ctkEventAdmin>(ref);context_->ungetService(ref);}//发送事件ctkDictionary message;if(eventAdmin)eventAdmin->postEvent(ctkEvent(text, message));
}
void MenuBar::insertMenuAndActions(const QJsonObject &obj)
{if(obj.isEmpty()){return;}QString key = obj["menu_name"].toString();if(menu_map_.contains(key)){QAction *action = new QAction(obj["action_name"].toString() ,this);action->setIcon(QIcon(obj["picture"].toString()));connect(action, &QAction::triggered, this, &MenuBar::actionTriggered);if(actions_map_.contains(key)){actions_map_[key].insert(obj["num"].toInt(), action);}else{actions_map_.insert(key, QList<QAction*>() << action);}}else{QMenu *menu = new QMenu(key, this);menu_map_.insert(key, menu);QAction *action = new QAction(obj["action_name"].toString() ,this);action->setIcon(QIcon(obj["picture"].toString()));connect(action, &QAction::triggered, this, &MenuBar::actionTriggered);actions_map_[key].insert(obj["num"].toInt(), action);if(actions_map_.contains(key)){actions_map_[key].insert(obj["num"].toInt(), action);}else{actions_map_.insert(key, QList<QAction*>() << action);}}menu_map_[key]->clear();menu_map_[key]->addActions(actions_map_[key]);
}
QMenu *MenuBar::getMenu(const QString &name)
{return menu_map_[name];
}
  1. 给定注册接口,按照以下的形式去发送注册菜单的事件

actionregister.h

#ifndef CTKPLUGIN_ACTIONREGISTER_H
#define CTKPLUGIN_ACTIONREGISTER_H
#include "ctkDictionary.h"
#include <QJsonObject>
/****** @brief 注册菜单栏* @param name     是现实在action的菜单menu的名称* @param id       是该菜单的唯一编号(也是菜单点击后的事件的id, 事件根据此id发送)* @param num      是排在第几个位置(如果有重复的可能会按照后注册插件的来)* @param picture  是图标的路径*/
struct ActionData
{QString menu_name;QString action_name;int num{-1};QString picture;
};
class ActionDictionary
{
public:ActionDictionary() = default;~ActionDictionary() = default;void registerAction(const ActionData &actionData);ctkDictionary getDictionary() { return dictionary; }private:ctkDictionary dictionary;
};
void ActionDictionary::registerAction(const ActionData &actionData)
{QJsonObject obj;obj.insert("menu_name", actionData.menu_name);obj.insert("action_name", actionData.action_name);obj.insert("num", actionData.num);obj.insert("picture", actionData.picture);dictionary.insert(actionData.action_name, QVariant::fromValue(obj));
}
#endif //CTKPLUGIN_ACTIONREGISTER_H
  1. 在aboutplugin中发送对应的事件
void AboutPlugin::registerToMainWindow()
{//获取事件服务接口ctkServiceReference ref;ctkEventAdmin* eventAdmin{nullptr};ref = context_->getServiceReference<ctkEventAdmin>();if(ref){eventAdmin = context_->getService<ctkEventAdmin>(ref);context_->ungetService(ref);}//发送事件ActionData data;data.action_name = "About";data.menu_name = "Help";data.picture = "";data.num = 1;ActionDictionary a;a.registerAction(data);ctkDictionary message = a.getDictionary();if(eventAdmin)eventAdmin->postEvent(ctkEvent("mainwindow_action", message));
}

之前关闭的时候崩溃错误

之前的代码关闭的时候mainwindow析构还会报一个线程错误,我们把析构使用信号去处理。

具体修改见项目。这里就不贴优化部分的代码了,思路就是使用信号去处理界面的析构,否则会因为析构代码不在界面线程调用而崩溃。


http://www.ppmy.cn/news/703762.html

相关文章

万字综述,GNN在NLP中的应用,建议收藏慢慢看

今天为大家解读的是由京东硅谷研发中心首席科学家吴凌飞博士等研究者最新发表的GNN for NLP综述&#xff0c;几乎覆盖了围绕NLP任务的所有GNN相关技术&#xff0c;是迄今为止GNN for NLP领域最全面最新的综述性文献。 论文标题&#xff1a;Graph Neural Networks for Natural L…

这次,带你写个操作系统

都说操作系统&#xff08;简称 OS &#xff09;&#xff0c;是程序员的三大浪漫之一&#xff0c;我们经常会用“灵魂、大脑、内核、基石”等词来形容它&#xff0c;足以见得它对计算机而言有多么重要。 在实际工作中也确实如此&#xff0c;很多遇到的疑难杂症&#xff0c;都和操…

公司来了个北大妹子,一人写了个操作系统,折服了。。。

大家好&#xff0c;我是肉哥&#xff01; 都说操作系统&#xff08;简称 OS &#xff09;&#xff0c;是程序员的三大浪漫之一&#xff0c;我们经常会用“灵魂、大脑、内核、基石”等词来形容它&#xff0c;足以见得它对计算机而言有多么重要。 在实际工作中也确实如此&#xf…

深度2万字好文:图像处理-基于 PyTorch 的 YOLO v5 表情识别(附源代码)

前言 本文利用YOLOV5对手势进行训练识别,并识别显示出对应的emoji,如同下图: 本文整体思路如下。提示:本文含完整实践代码,代码较长,建议先看文字部分的实践思路 以下是我为大家准备的几个精品专栏,喜欢的小伙伴可自行订阅,你的支持就是我不断更新的动力哟! MATLAB…

用YOLOv5模型识别出表情!

↑↑↑关注后"星标"Datawhale 每日干货 & 每月组队学习&#xff0c;不错过 Datawhale干货 作者&#xff1a;闫永强&#xff0c;算法工程师&#xff0c;Datawhale成员 本文利用YOLOV5对手势进行训练识别&#xff0c;并识别显示出对应的emoji&#xff0c;如同下图…

零基础小白怎么学习3D建模?过来人给的一些学习建议,先马后看

零基础小白学3D建模建议从以下三个方面学习&#xff1a; 一是学习软件&#xff0c;了解软件的功能&#xff0c;基本命令和操作。能熟练使用软件来雕刻东西&#xff0c;这方面练习方法就是自己动手去做&#xff0c;然后看相应教程&#xff0c;从别人雕刻全过程的视频中了解软件…

关键点检测项目代码开源了!

Datawhale干货 作者&#xff1a;闫永强&#xff0c;算法工程师&#xff0c;Datawhale成员 本文通过自建手势数据集&#xff0c;利用YOLOv5s检测&#xff0c;然后通过开源数据集训练squeezenet进行手部关键点预测&#xff0c;最后通过指间的夹角算法来判断具体的手势&#xff0…

用生物知识解读“新冠病毒”,生物竞赛、高考考点,先马后看!

临近过年&#xff0c;新冠病毒却卷土重来&#xff0c;再一次牵动了所有人的内心&#xff0c;它也注定将成为近两年来考试的大热点&#xff0c;所以透彻的分析新冠病毒自带的各种考点是学生们的必须要做的事情。 今天质心姐姐就带大家用生物学知识分析新冠病毒的原理&#xff0…