Qt 封装系统托盘类进行使用(系统托盘、托盘菜单、托盘消息框)

系统托盘,相信大家并不陌生,在使用电脑过程中我们无时无刻都在进行使用着它。今天记录下自己写的qt程序如何使用系统托盘。

由标题可知,本篇博客介绍的是:自定义类继承自系统托盘类,并实现其中所需功能。由此写好的类,可以给任何项目使用!

先看效果图:

消息框:
在这里插入图片描述
系统托盘:
在这里插入图片描述
托盘菜单:
在这里插入图片描述


新建类并继承自托盘类

首先新建类,并继承自系统托盘类QSystemTrayIcon
包含其头文件:#include <QSystemTrayIcon>

并定义私有变量Widget类型,也得包含头文件:#include <QWidget>

如下代码:

#include <QSystemTrayIcon>
#include <QWidget>


class Systray : public QSystemTrayIcon {
	Q_OBJECT

public:
	Systray(QWidget *parent);	// 不能指定默认值
	~Systray();

private:
	QWidget *m_pParent;	// 父类,用于显示窗体
};

注意:

  1. 构造函数中不能指定默认值,因为new该类对象是需要传入父类的。
  2. 一定要定义私有QWidget 类型变量用于存储传入的父类widget对象。

初始化托盘

新建初始化函数,用于准备工作。(设置工具提示、设置托盘图标、信号与槽的绑定)

private:
	void initSysTray();		// 初始化托盘


// 初始化
void Systray::initSysTray() {
	setToolTip(tr("我的五子棋"));		// 设置工具提示
	setIcon(QIcon("chess.ico"));	// 设置托盘图标

	// 点击托盘所作的操作
	connect(this, &Systray::activated, this, &Systray::onIconActivated);

	// 点击消息框后显示主页面
	connect(this, &Systray::messageClicked, [this] {
		m_pParent->activateWindow();
		m_pParent->showNormal();
	});

	// 显示系统托盘消息框
	connect(this, &Systray::showTrayMessage, this, &Systray::showMessage);
}

第一个connect:我们单击或者双击或者右键单击系统托盘时会发出activated信号,将其与我们自己写的槽函数进行绑定,可以实现显示与退出等操作!

第二个connect:最小化后电脑右下角会显示托盘消息框,其有一个消息点击信号,将其与我们自己写的槽函数进行绑定,可以实现点击显示窗体效果。

第三个connect:自己定义的信号与自己定义的槽函数进行绑定,用于实现最小化后发射信号触发托盘消息框显示。

现在来实现第一个connect绑定的槽函数

注意槽函数的参数

private slots:
	void onIconActivated(QSystemTrayIcon::ActivationReason reason);	// 处理事件函数


void Systray::onIconActivated(QSystemTrayIcon::ActivationReason reason) {
	if (reason == QSystemTrayIcon::Trigger) {		// 点击触发
		// 显示窗体
		m_pParent->activateWindow();
		m_pParent->showNormal();

	} else if (reason == QSystemTrayIcon::Context) {	// 右键触发
		// 显示菜单
		trayMenu->exec(QCursor::pos());	// 在鼠标的位置显示
	}

通过参数进行判断,可以知道鼠标对系统托盘做了那些操作,进而对于做出相应操作。

除了上面两种外还有一下几种:
This enum describes the reason the system tray was activated.

ConstantValueDescription
QSystemTrayIcon::Unknown0未知的原因
QSystemTrayIcon::Context1请求系统托盘条目的上下文菜单
QSystemTrayIcon::DoubleClick2系统托盘入口被双击
QSystemTrayIcon::Trigger3系统托盘条目被点击
QSystemTrayIcon::MiddleClick4用鼠标中键点击系统托盘入口

添加托盘菜单

.h文件中定义私有变量菜单对象。QMenu *trayMenu; // 菜单
需包含头文件:#include <QMenu>

新建私有函数添加菜单

private:
	void addSysTrayMenu();	// 添加菜单

// 菜单
void Systray::addSysTrayMenu() {
	trayMenu = new QMenu(m_pParent);		// 新建菜单,指定父对象
	// 新建菜单子项
	QAction *action1 = new QAction(trayMenu);
	QAction *action2 = new QAction(trayMenu);

	action1->setIcon(QIcon("show.png"));	// 设置菜单图标
	action1->setText(QString("Show"));		// 设置带单文本
	action2->setIcon(QIcon("close.png"));
	action2->setText(QString("Quit"));


	// 添加菜单子项
	trayMenu->addAction(action1);
	trayMenu->addAction(action2);

	// 显示窗体
	connect(action1, &QAction::triggered, [this](bool) { 
		m_pParent->activateWindow();
		m_pParent->showNormal();
	});

	// 退出
	connect(action2, &QAction::triggered, [this](bool) { this->m_pParent->close(); });
}

注意:
new菜单对象时,指定的父对象是我们通过构造函数传入来的值,不是this。

给菜单新建子项,并指定菜单,设置图标,文本。最后将其添加到菜单中。

为子项菜单绑定信号与槽:
第一个connect:显示主窗体
第二个connect:关闭主窗体

上面绑定信号与槽,槽函数使用的是lambada表达式。


做完上面两个操作后,就可以在构造函数中调用这些函数了。

Systray::Systray(QWidget *parent) : m_pParent(parent), QSystemTrayIcon(parent) {

	initSysTray();		// 初始化托盘
	addSysTrayMenu();	// 初始化菜单

	this->show();		// 显示托盘
}

注意:需要调用show()函数,否则托盘菜单是无法显示的。


实现消息框

.h文件中定义信号,用于触发显示消息框

signals:
	void showTrayMessage();		// 触发显示系统托盘消息框

现在来实现上面第三个connect绑定的槽函数

private:
	void showMessage();		// 显示消息框


// 消息框
void Systray::showMessage() {
	QSystemTrayIcon::showMessage("Notice",				// 消息窗口标题
							  "The form is minimized!",// 消息内容
							  QSystemTrayIcon::MessageIcon::Information,// 消息窗口图标 
							  1000);					// 消息窗口显示时长(经测试,win10系统下,没有效果)
}

使用QSystemTrayIcon类调用静态showMessage方法。
参数一:消息窗口标题
参数二:消息内容
参数三: 消息窗口图标
参数四:消息窗口显示时长(经测试,win10系统下,没有效果)

上面我们自定义的函数名与托盘类的消息函数名相同,所以使用类名进行区分调用。


能观看此篇博客到这里的朋友们,按照上面的步骤做下来,恭喜你们已经成功封装好自己的托盘类了。下面就是调用。

在需要实现系统托盘的的程序中,加入此类的头文件。
在构造函数中new出自定托盘类的对象,并传入this参数,即可自动实现全部功能。

#include "Systray.h"		// 托盘


Qt_Gobang::Qt_Gobang(QWidget *parent)
    : QWidget(parent) {
    ui.setupUi(this);
	
	// 此处省略一万行代码......

	// 托盘
	m_pTray = new Systray(this);
}

仅需new出托盘对象即可,无需再做其他操作,甚是方便!

当然还有一个操作,当我们点击主窗体最小化按钮时,我们需要将窗体隐藏,否则就会最小化到任务栏中了。
加入下面函数即可实现:
加入头文件:#include <QEvent>

protected:
	// 捕捉最小化按钮
	void changeEvent(QEvent *event);


void Qt_Gobang::changeEvent(QEvent *event) {
	// 事件类型是否等于窗体状态发生改变事件
	if (event->type() != QEvent::WindowStateChange) return;

	// 窗体状态等于最小化按钮
	if (this->windowState() == Qt::WindowMinimized) {
		this->hide();	// 隐藏窗体
		emit m_pTray->showTrayMessage();	// 最小化后消息提示框
	}
}

隐藏窗体后应发射信号,调出托盘消息框!
emit m_pTray->showTrayMessage(); // 最小化后消息提示框

还有以下几种枚举:

ConstantValueDescription
Qt::WindowNoState0x00000000窗口没有设置状态(正常状态)
Qt::WindowMinimized0x00000001窗口最小化(即图标化)
Qt::WindowMaximized0x00000002窗口最大化
Qt::WindowFullScreen0x00000004该窗口填满了整个屏幕,周围没有任何边框
Qt::WindowActive0x00000008该窗口是活动窗口,即它有键盘焦点

全部代码:

如果你照着上面步骤无法实现,可以复制下面代码到自己的项目中,新建类粘贴,即可实现使用。

.h文件

#pragma once

#include <QSystemTrayIcon>
#include <QWidget>
#include <QMenu>

class Systray : public QSystemTrayIcon {
	Q_OBJECT

public:
	Systray(QWidget *parent);
	~Systray();


private slots:
	void onIconActivated(QSystemTrayIcon::ActivationReason reason);	// 处理事件函数

private:
	void initSysTray();		// 初始化托盘
	void addSysTrayMenu();	// 添加菜单
	void showMessage();		// 显示消息框


signals:
	void showTrayMessage();		// 触发显示系统托盘消息框

private:
	QWidget *m_pParent;	// 父类,用于显示窗体
	QMenu *trayMenu;	// 菜单
};

.cpp文件

#include "Systray.h"

#pragma execution_character_set("utf-8")    // qt支持显示中文


Systray::Systray(QWidget *parent) : m_pParent(parent), QSystemTrayIcon(parent) {

	initSysTray();		// 初始化托盘
	addSysTrayMenu();	// 初始化菜单

	this->show();		// 显示托盘
}

Systray::~Systray() {
}


// 事件触发
void Systray::onIconActivated(QSystemTrayIcon::ActivationReason reason) {
	if (reason == QSystemTrayIcon::Trigger) {		// 点击触发
		m_pParent->activateWindow();
		m_pParent->showNormal();

	} else if (reason == QSystemTrayIcon::Context) {	// 右键触发
		trayMenu->exec(QCursor::pos());
	}
}



// 初始化
void Systray::initSysTray() {
	setToolTip(tr("我的五子棋"));		// 设置工具提示
	setIcon(QIcon(tr("chess.ico")));	// 设置托盘图标

	// 点击托盘所作的操作
	connect(this, &Systray::activated, this, &Systray::onIconActivated);

	// 点击消息框后显示主页面
	connect(this, &Systray::messageClicked, [this] {
		m_pParent->activateWindow();
		m_pParent->showNormal();
	});

	// 显示系统托盘消息框
	connect(this, &Systray::showTrayMessage, this, &Systray::showMessage);
}



// 菜单
void Systray::addSysTrayMenu() {
	trayMenu = new QMenu(m_pParent);		// 新建菜单,指定父对象
	// 新建菜单子项
	QAction *action1 = new QAction(trayMenu);
	QAction *action2 = new QAction(trayMenu);

	action1->setIcon(QIcon("show.png"));	// 设置菜单图标
	action1->setText(QString("Show"));		// 设置带单文本
	action2->setIcon(QIcon("close.png"));
	action2->setText(QString("Quit"));


	// 添加菜单子项
	trayMenu->addAction(action1);
	trayMenu->addAction(action2);

	// 显示窗体
	connect(action1, &QAction::triggered, [this](bool) { 
		m_pParent->activateWindow();
		m_pParent->showNormal();
	});

	// 退出
	connect(action2, &QAction::triggered, [this](bool) { this->m_pParent->close(); });
}


// 消息框
void Systray::showMessage() {
	QSystemTrayIcon::showMessage("Notice",				// 消息窗口标题
							  "The form is minimized!",// 消息内容
							  QSystemTrayIcon::MessageIcon::Information,// 消息窗口图标 
							  1000);					// 消息窗口显示时长(经测试,win10系统下,没有效果)
}

总结:
网上有许多博客也都有介绍系统托盘的使用,但是他们讲的都是在主程序构造函数中进行操作的,虽然可以实现,但是却显得代码很臃肿,不是很好看;当你自己定义类实现时,代码就清爽很多了。

  • 7
    点赞
  • 19
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 5
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

cpp_learners

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值