首页 > 其他分享 >系统托盘如何实现

系统托盘如何实现

时间:2023-07-10 21:00:12浏览次数:36  
标签:菜单 parent 实现 系统托盘 QSystemTrayIcon 如何 customMenu MySysTray void

qt中有这么一个类(系统托盘类QSystemTrayIcon),但是我们要设置一些自定义功能,所以要对此类进行重写。

1.如何调用:需要的地方使用自定义托盘类:MySysTray* systray = new MySysTray(this);若是仅仅在此继承类中改变图标的话,是会在托盘中显示出来的,但是却没有任何点击效果(即点击后无反应)。

2.

//MySysTray类头文件
#pragma once
#include <QSystemTrayIcon>
#include <QWidget>
class MySysTray:public QSystemTrayIcon{ Q_OBJECT public:
   MySysTray(QWidget *parent);
~MySysTray();
public slots:
   void onIconActivated(QSystemTrayIcon::ActivationReason reason); //自定义槽函数非继承而来,响应点击图标 参数:触发/内容
private:
   void initSystemTray();    
private:
   QWidget* m_parent;
}

3.

//MySysTray类cpp
#include "MySysTray.h"

void MySysTray::MySysTray(QWidget *parent):m_parent(parent),QSystemTrayIcon(parent){
  initSystemTray(); 
  show();

}
void MySysTray::onIconActivated(QSystemTrayIcon::ActivationReason reason){
  if(reason==QSystemTrayIcon::Trigger){  
    m_parent->show();
    m_parent->activatedWindow();}
}
void MySysTray::initSystemTray(){ 
  
    setIcon(QIcon([pathname])); //pathname是图片路径
    setToolTip(QStringLiteral("QQ_奇牛科技"));
    connect(this, SIGNAL(activated(QSystemTrayIcon::ActivationReason)), this, SLOT(onIconActivated(QSystemTrayIcon::ActivationReason)));
}

 4.以上左键点击托盘图标时(触发),是能够显示出窗口的,我们需要通过托盘实现退出功能,右击托盘图标发射(内容)信号,为了响应

这个信号,我们自行增加一个菜单,即右击后 ,可以有菜单进行选择功能。为了完成这个功能,我们需要重写菜单类。

#include <QMenu>
#include <QMap>

class CustomMenu:public QMenu{ Q_OBJECT
public:
  CustomMenu(QWidget *parent = nullptr):QMenu(parent){
    setAttribute(Qt::WA_TranslucentBackground);//设置透明
    //CommonUtils::loadStyleSheet(this,"Menu"); //这是使用自定义类CommonUtils中的样式方法,无需关注
   }

  ~CustomMenu(){}

  public:
    void addCustomMenu(const QString& text, const QString& icon,const QString& name){

      QAction* pAction = addAction(QIcon(icon), name);

      m_menuActionMap.insert(text, pAction);

    }
    QAction* getAction(const QString& text){

      return m_menuActionMap[text];

    }

private:
    QMap<QString, QAction*> m_menuActionMap;      //映射到动作按钮上,以便发射信号

}

5.如何在自定义的系统托盘类中使用:(在原基础上增加代码)

//MySysTray类头文件
#pragma once
#include <QSystemTrayIcon>
#include <QWidget>
class MySysTray:public QSystemTrayIcon{
        Q_OBJECT  
public: MySysTray(QWidget *parent);     
        ~MySysTray();
public slots:   
void onIconActivated(QSystemTrayIcon::ActivationReason reason); //自定义槽函数非继承而来,响应点击图标 参数:触发/内容private:    void initSystemTray();
private:
     void addSystrayMenu(); private:   QWidget* m_parent; }
//MySysTray类cpp
#include "MySysTray.h"
#include "CustomMenu"
void MySysTray::MySysTray(QWidget *parent):m_parent(parent),QSystemTrayIcon(parent){
  initSystemTray(); 
  show();
}
void MySysTray::onIconActivated(QSystemTrayIcon::ActivationReason reason){
  if(reason==QSystemTrayIcon::Trigger){  
    m_parent->show();
    m_parent->activatedWindow();}
  if(reason==QSystemTrayIcon::Context){
    addSystrayMenu();
  } } void MySysTray::initSystemTray(){      setIcon(QIcon([pathname])); //pathname是图片路径     setToolTip(QStringLiteral("QQ_奇牛科技"));     connect(this, SIGNAL(activated(QSystemTrayIcon::ActivationReason)), this, SLOT(onIconActivated(QSystemTrayIcon::ActivationReason))); }
void MySysTray::addSystrayMenu(){
    CustomMenu* customMenu = new CustomMenu(m_parent);
    customMenu->addCustomMenu("onShow",[pathname],QStringLiteral("显示"));
    customMenu->addCustomMenu("onQuit",[pathname],QStringLiteral("退出"));
    connect(customMenu->getAction("onShow"),SIGNAL(triggered(bool)),m_parent,SLOT(onShowNormal(bool)));
    connect(customMenu->getAction("onQuit"),SIGNAL(triggered(bool)),m_parent,SLOT(onShowQuit(bool)));
    ////让菜单进入事件循环,接收鼠标的操作
    customMenu->exec(QCursor::pos());
    delete customMenu;
    customMenu = nullptr;
}

第5步中有两个问题:

1.为什么要让菜单事件进入循环?

答:若省略////让菜单进入事件循环,接收鼠标的操作的下面三行代码,我们右击托盘图标时,是不会有菜单显示出来的,若是写一句:customMenu->show()则右击托盘时是有

菜单显示的,且能够达到作用效果。只不过显示的位置不符合预期,故此我们这里采用事件循环:customMenu->exec(QCursor::pos());这就使得能够显示,并且在鼠标位置显示。

这句函数的作用就是显示菜单,其中的参数(QCursor::pos())可以指示菜单显示位置,另外该函数可以返回单击选中项。

 

2.为什么还要手动delete菜单,对象树怎么了?

若是直接选择退出的话,可以不手动删除,由对象树来删,但若是选择的是显示的话,每次调用菜单的时候都会开辟一块内存,泄露了,故此要手动删除。(退出事件循环后,继续执行完下面的delete语句。)

标签:菜单,parent,实现,系统托盘,QSystemTrayIcon,如何,customMenu,MySysTray,void
From: https://www.cnblogs.com/ylww/p/17538559.html

相关文章

  • 【Python】Locust持续优化:InfluxDB与Grafana实现数据持久化与可视化分析
    前言在进行性能测试时,我们需要对测试结果进行监控和分析,以便于及时发现问题并进行优化。Locust在内存中维护了一个时间序列数据结构,用于存储每个事件的统计信息。这个数据结构允许我们在Charts标签页中查看不同时间点的性能指标,但是正因为LocustWebUI上展示的数据实际上是存储......
  • 支持向量机学习笔记--实现篇(三)
    支持向量机学习笔记(三)前言两篇文章阐述了支持向量机的原理,在数学的海洋中遨游了快一周,实在撑不下去了,现在准备亲自来实现一把支持向量机的学习算法,序列最小最优化算法,依然需要数学知识和少量的编程基础。参考的书籍为李航的《统计学习方法》和PeterHarrington的《机器学习实战》,参......
  • 使用递归函数来实现输入正整数,将正整数分解鸡(质因)数
    介绍一下递归函数:当我们定义一个函数时,如果函数内部调用了自身,那么这个函数就称为递归函数。递归函数是一种解决问题的方法,它将大问题分解为相同或类似的小问题,并通过逐步解决这些小问题来解决整个问题。使用递归函数的核心思想是将一个问题拆解为更简单的子问题,并且解决子问题的方......
  • Windows计算机如何在线打开Sketch文件?
    自Sketch诞生以来,只有Mac版本。Windows计算机如何在线打开Sketch文件?即时设计已经解决了你遇到的大部分问题,不占用内存也是免费的。您可以使用此软件直接在线打开Sketch文件,完整预览并导出CSS、SVG、PNG等,还具有编辑功能! 如何导入Sketch文件?如果需要切换设计工具,能够......
  • 如何使用C++11 STD::THREAD设置堆栈大小?
    本教程将介绍如何使用C++11std::thread设置线程的堆栈大小。C++11std::thread是一种轻量级的多线程实现,它的灵活性使得它成为一个流行的选择。但是,在某些情况下,您可能需要设置线程的堆栈大小来满足您的需求。在开始本教程之前,我们假设您已经熟悉了C++11std::thread的基础知识......
  • 多行文本转成一行的实现方法
    哈喽大家好,我是咸鱼不知道你们有没有遇到过下面的情况,以我为例有时候我会收到批量操作服务器的需求,且我会拿到一个服务器ip列表,它是一个多行的形式,如下所示#ip列表192.168.0.1192.168.0.2192.168.0.3192.168.0.4192.168.0.5192.168.0.6但我使用saltstack进行批量......
  • 2023-07-10:Kafka如何做到消息不丢失?
    2023-07-10:Kafka如何做到消息不丢失?答案2023-07-10:Kafka采用多种机制来确保消息的不丢失,其中包括副本机制、ISR(In-SyncReplicas)机制以及ACK机制等。1.副本机制Kafka通过副本机制来确保消息不会丢失。在Kafka中,每个分区都可以配置多个副本,每个副本保存分区的完整拷贝。当一个副本宕......
  • JAVA集成velocity实现对已有模板替换(占位符变量)替换
      平时我们如果有一些简单的模板替换需求,比如有个txt文件,或者代码生成模板文件要根据传入的变量替换成具体的值就可以使用这个框架 依赖<dependency><groupId>org.apache.velocity</groupId><artifactId>velocity-engine-core</artifactId>......
  • 2023-07-10:Kafka如何做到消息不丢失?
    2023-07-10:Kafka如何做到消息不丢失?答案2023-07-10:Kafka采用多种机制来确保消息的不丢失,其中包括副本机制、ISR(In-SyncReplicas)机制以及ACK机制等。1.副本机制Kafka通过副本机制来确保消息不会丢失。在Kafka中,每个分区都可以配置多个副本,每个副本保存分区的完整拷贝。当一个......
  • Java实现浏览器端大文件分片上传实例
    ​ 上周遇到这样一个问题,客户上传高清视频(1G以上)的时候上传失败。一开始以为是session过期或者文件大小受系统限制,导致的错误。查看了系统的配置文件没有看到文件大小限制,web.xml中seesiontimeout是30,我把它改成了120。但还是不行,有时候10分钟就崩了。同事说,可能是客户这里......