Loading [MathJax]/jax/output/CommonHTML/config.js
前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
社区首页 >专栏 >用Qt写软件系列四:定制个性化系统托盘菜单

用Qt写软件系列四:定制个性化系统托盘菜单

作者头像
24K纯开源
发布于 2018-01-18 02:37:41
发布于 2018-01-18 02:37:41
2.9K00
代码可运行
举报
文章被收录于专栏:24K纯开源24K纯开源
运行总次数:0
代码可运行

导读

    一款流行的软件,往往会在功能渐趋完善的时候,通过改善交互界面来提高用户体验。毕竟,就算再牛逼的产品,躲藏在糟糕的用户界面之后总会让用户心生不满。界面设计需综合考虑审美学、心理学、设计学等多因素,是一份精细活。这篇博文仍然以Qt的使用为主旨,探讨一下在Qt中如何进行系统托盘的个性化定制。

介绍

    首先我们看看几款知名软件的系统托盘设计:

    上图是金山卫士的系统托盘菜单设计。我们稍作分析:整个托盘菜单窗口是个半透明的设计,窗口边框进行了圆角处理。底部的菜单项包含三个Button,倒数第二、三个菜单项的右部还加上了一个自定义的单选按钮。顶部菜单项则包含一个评级组件;其他菜单项则没有什么特别,加上对应的图标即可完成设计。但是可能由于整个背景色的缘故,导致整体效果看起来灰蒙蒙的,不太亮堂。

     上图是360安全卫士的托盘菜单。顶部和底部的两个菜单项都将背景色设置成了360安全卫士的主题色,加上了两个标签和按钮。其他菜单项保持不变。另外,菜单的背景色也被设置成了白色。整个菜单的设计较为简洁、清爽。虽然并不喜欢用360安全卫士,但是并不妨碍我对其产品外观设计的赞赏。

原型设计

     既然有了上述两款产品的参考,我们也可以试着设计下自己的系统托盘。首先我们需要一个原型设计工具,将草图绘制好我们才能用代码将最终结果显示出来。这里推荐一个原型设计工具:Balsqmiq mockup。这款工具使用简单,其提供的原型组件非常丰富,使用会觉得非常方便。

     根据初步设想,我设计了如下的一个原型草图:

      在布局方面基本上综合了金山卫士和360安全卫士的设计特点。顶部菜单项部署两个Label, 一个用来显示应用程序的窗口标题或产品名称,另一个显示为go to visit,可以响应鼠标点击事件。底部菜单项和金山卫士一样,设置了三个按钮:Update, about, exit,使用水平均匀布局。其他的菜单项则和普通菜单项没有区别。 基本上,一个自定义的托盘菜单已经跃然而出。

代码实现

      根据上述的原型设计,我们要做的准备工作显然就是准备好图片。对于没有美工技能的程序员来说,寻找界面图片素材显然是一大难题。做不出图片显然只好去网上搜索了。本人在网上下载了一堆的图片压缩包,有一个值得推荐:异次元图标。另外还有一个图片搜索网站也值得推荐。在这里我准备的图片如下:

      每个图片都取了一个别名,这样在代码中我们直接使用图片别名,从而消除与图片具体名称的藕合性。资源准备好之后我们需要开始编码了。参考本人曾经写过的一篇博文(使用Qt创建系统托盘),可以实现一个默认主题的系统托盘菜单。但是这里我们要实现自定义托盘菜单,我们从QSystemTray派生一个子类,并定义好相关的类成员变量:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
QMenu* m_trayMenu;

QWidget* m_topWidget;
QWidgetAction* m_topWidgetAction;
QLabel* m_topLabel;
QLabel* m_homeBtn;

QWidget* m_bottomWidget;
QWidgetAction* m_bottomWidgetAction;
QPushButton* m_updateBtn;
QPushButton* m_aboutBtn;
QPushButton* m_exitBtn;

QAction* m_runOnSystemBoot;
QAction* m_helpOnline;
QAction* m_homePage;
QAction* m_notification;
QAction* m_settings;

  显然,我们注意到一个平时没有接触到的:QWidgetAction。这个类自Qt 4.2引入,继承自QAction。根据类名也可以推测出其含义:使用QWidget来充当Menu的Action。于是,我们似乎明白了自定义菜单的精髓:用Widget来做Action。这里我们主要定义顶部菜单项和底部菜单项。因此我们定义了两个QWidgetAction。另外,我们还有一个疑问就是:布局好的Widget如何"伪装"成Action插入到菜单项中去呢?我们可以使用QWidgetAction的setDefaultWidget()方法来完成这项工作。后面的代码将会有说明。

      此外,我们还注意到:360安全卫士的底部菜单项和顶部菜单项的背景色都是绿色的这又该如何实现呢?一种可行的方法是,安装一个事件过滤器(Event Filter)。当过滤到绘制事件并且绘制的组件是顶部菜单项和底部菜单项时,我们改变绘制方式。代码如下:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
bool SystemTray::eventFilter(QObject *obj, QEvent *event)
{
	if (obj == m_topWidget && event->type() == QEvent::Paint)
	{
		QPainter painter(m_topWidget);
		painter.setPen(Qt::NoPen);
		painter.setBrush(QColor(42, 120, 192));
		painter.drawRect(m_topWidget->rect());
	}
	return QSystemTrayIcon::eventFilter(obj, event);
}

  在完成了我们自己的绘制工作之后,还得再调用父类的事件过滤器,以免漏掉其他过滤工作。eventFilter()是一个protected方法,我们要在头文件中进行重写。

      接下来要做的工作就是完成顶部和底部菜单项的绘制工作。先看看顶部菜单项如何绘制:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
void SystemTray::createTopWidget()
{
	m_topWidget = new QWidget();
	m_topWidgetAction = new QWidgetAction(m_trayMenu);
	m_topLabel = new QLabel(QStringLiteral("HUST Information Security Lab"));
	m_topLabel->setObjectName(QStringLiteral("WhiteLabel"));
	m_homeBtn = new QLabel(QStringLiteral("Visit"));
	m_homeBtn->setCursor(Qt::PointingHandCursor);
	m_homeBtn->setObjectName(QStringLiteral("WhiteLabel"));

	QVBoxLayout* m_topLayout = new QVBoxLayout();
	m_topLayout->addWidget(m_topLabel, 0, Qt::AlignLeft|Qt::AlignVCenter);
	m_topLayout->addWidget(m_homeBtn, 0, Qt::AlignRight|Qt::AlignVCenter);

	m_topLayout->setSpacing(5);
	m_topLayout->setContentsMargins(5, 5, 5, 5);

	m_topWidget->setLayout(m_topLayout);
	m_topWidget->installEventFilter(this);
	m_topWidgetAction->setDefaultWidget(m_topWidget);
}

  我们声明了两个Label标签,作用在上文已说明。然后用垂直布局管理器将两个标签分左右放置。注意语句:m_topWidget->installEventFilter(this)。这条语句完成了过滤器的安装。指针this表明窗口事件将先发往当前类的eventFilter()方法进行处理,如果不处理再发往其他类的过滤器进行处理。底部菜单项的初始化大致类似:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
void SystemTray::createBottomWidget()
{
	m_bottomWidget = new QWidget();
	m_bottomWidgetAction = new QWidgetAction(m_trayMenu);

	m_updateBtn = new QPushButton(QIcon(":/menu/update"), QStringLiteral("Update"));
	m_updateBtn->setObjectName(QStringLiteral("TrayButton"));
	m_updateBtn->setFixedSize(60, 25);

	m_aboutBtn = new QPushButton(QIcon(":/menu/about"), QStringLiteral("About"));
	m_aboutBtn->setObjectName(QStringLiteral("TrayButton"));
	m_aboutBtn->setFixedSize(60, 25);

	m_exitBtn = new QPushButton(QIcon(":/menu/quit"), QStringLiteral("Exit"));
	m_exitBtn->setObjectName(QStringLiteral("TrayButton"));
	m_exitBtn->setFixedSize(60, 25);

	QHBoxLayout* m_bottomLayout = new QHBoxLayout();
	m_bottomLayout->addWidget(m_updateBtn, 0, Qt::AlignCenter);
	m_bottomLayout->addWidget(m_aboutBtn, 0, Qt::AlignCenter);
	m_bottomLayout->addWidget(m_exitBtn, 0, Qt::AlignCenter);

	m_bottomLayout->setSpacing(5);
	m_bottomLayout->setContentsMargins(5,5,5,5);

	m_bottomWidget->setLayout(m_bottomLayout);
	m_bottomWidgetAction->setDefaultWidget(m_bottomWidget);
}

  分别对三个按钮设置了大小和图标。具体的外观样式则使用了QSS来进行控制,因此我们还为每个按钮设置了一个Object Name。这个Object Name在QSS中充当ID选择器,便于样式控制。那么样式文件该如何编写呢?具体参看如下所示:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
QMenu{
    background:white;
    border:1px solid lightgray; # 边框为灰色
}

QMenu::item{
    padding:0px 20px 0px 20px;
    margin-left: 5px;
    height:25px;
}

QMenu::item:selected:enabled{
    background: lightgray;   # 菜单项选中时背景色设置为浅灰色
    color: white;            # 文本颜色设置为白色,否则看不清文本内容了
}

QMenu::separator{
    height:1px;
    background: lightgray;   # 菜单分割线也设置为浅灰色
    margin:2px 0px 2px 0px;
}

QMenu::item:selected:!enabled{
    background:transparent;
}

QPushButton#TrayButton {
    border: none;    # 无边框按钮
    background: transparent;  # 按钮背景设置为透明,这样不会受到默认主题颜色干扰
}

QPushButton#TrayButton:hover {
    background: rgb(233, 237, 252);  # 鼠标悬停时,按钮背景色设为淡色
    color: rgb(42, 120, 192);    # 鼠标悬停时,文本颜色不变
}

  基本上,使用上面的样式设置就可完成基本样式设置。其他代码就不再详细叙述。到此,我们的托盘菜单就完成了个性化定制工作。

效果图

      根据上述代码,我们实现的最终效果图如下:

       前面也说过:界面设计是一门学问,综合了设计学、心理学、审美学等多学科。要设计出让人耳目一新的产品界面,需要设计师具备相当的设计功力。但不管最终设计的怎么样,我们已经知道了,如何实现具备个人特点的托盘菜单!

参考

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2014-03-30 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
暂无评论
推荐阅读
编辑精选文章
换一批
【QT】系统事件入门 -- 文件 QFile基础和示例
🔥 文件操作是应用程序必不可少的部分。Qt 作为⼀个通用开发库,提供了跨平台的文件操作能力。Qt 提供了很多关于⽂件的类,通过这些类能够对文件系统进行操作,如文件读写、文件信息获取、文件制或重命名等
IsLand1314
2025/03/21
710
【QT】系统事件入门 -- 文件 QFile基础和示例
Fdog系列(五):使用Qt模仿QQ实现登录界面到主界面,功能篇。
Fdog系列(三):使用腾讯云短信接口发送短信,数据库写入,部署到服务器,web收尾篇。
花狗Fdog
2021/05/06
3.2K0
【Python篇】PyQt5 超详细教程——由入门到精通(终篇)
在 PyQt5 中,菜单栏(QMenuBar)、工具栏(QToolBar)和状态栏(QStatusBar)是 QMainWindow 提供的标准控件,用于帮助用户更好地与应用程序交互。它们是桌面应用程序的常见组成部分:
半截诗
2024/10/09
1.7K0
【Python篇】PyQt5 超详细教程——由入门到精通(终篇)
用Qt写软件系列五:一个安全防护软件的制作(1)
引言       又有许久没有更新了。Qt,我心爱的Qt,为了找工作不得不抛弃一段时间,业余时间来学一学了。本来计划要写一系列关于Qt组件美化的博文,但是写了几篇之后就没坚持下去了。技术上倒是问题不大,主要是时间不够充裕。这段时间写几篇关于界面整体设计的博文,从最基础的界面元素开始,到最后构建一个页面元素丰富的桌面应用程序。Trojan Assessment Platform是一个原型设计项目,只是实现了有限的一部分功能。远远还称不上是一个评估平台。这里仅仅侧重于用Qt做界面的实现。 界面预览      
24K纯开源
2018/01/18
1.5K0
用Qt写软件系列五:一个安全防护软件的制作(1)
Qt Style Sheet实践(一):按钮及关联菜单
导读      正如web前端开发中CSS(Cascade Style Sheet)的作用一样,Qt开发中也可以使用修改版的QSS将逻辑业务和用户界面进行隔离。这样,美工设计人员和逻辑实现者可以各司其职而不受干扰。更重要的是,由于界面和逻辑处理是分离的,低耦合性使得代码重构的工作量可以减少到最小。QSS和CSS的语法几乎一致,除了Qt自身增加的一些属性之外,其余的属性都可以在CSS2或CSS3中找到对应的属性。因此,如果曾经有过CSS的使用经验,那么QSS的使用将游刃有余。关于QSS的使用实践,打算撰写一系
24K纯开源
2018/01/18
4.7K0
Qt Style Sheet实践(一):按钮及关联菜单
【QT】Qt 窗口 (QMainWindow)
QMainWindow 是一个为用户提供主窗口程序的类,继承自 QWidget 类,并且提供了一个预定义的布局。QMainWindow 包含一个菜单栏(menu bar)、多个工具栏(tool bars)、多个浮动窗口(铆接部件)(dock widgets)、⼀个状态栏(status bar) 和⼀个 中心部件(central widget),它是许多应用程序的基础,如文本编辑器,图片编辑器等。如下图为 QMainwindow 中 各组件所处的位置:
YoungMLet
2024/07/16
3830
【QT】Qt 窗口 (QMainWindow)
使用QT创建系统托盘
使用QT来创建一个系统托盘,事实上是一件很简单的事。为什么这么说?一是因为QT文档给出了比较详细的例子,二是QT的结构比较优雅,设计风格统一。但是在动手之前,我们要从哪里下手?虽然QT文档给出了一个比较详细的例子,但由于功能较多,所以看起来比较费劲。我们在这只是抽丝剥茧,只实现系统托盘这一个功能。 首先,使用QT creator创建一个GUI工程,继承于QDialog还是QMainWindow还是QWidget都无所谓。我们以继承QMainWindow为例说明。创建完毕之后,creator将自动生成一些文件
24K纯开源
2018/01/18
2.7K0
使用QT创建系统托盘
QT入门学习——从信号和槽到对话框,各种控件以及自定义控件
2.4默认创建有窗口类,yWidget,基类有三种选择:QWidget、QMainWindowQDialog
Arya
2024/10/31
4700
QT入门学习——从信号和槽到对话框,各种控件以及自定义控件
Fdog系列(四):使用Qt框架模仿QQ实现登录界面,界面篇。
Fdog系列(三):使用腾讯云短信接口发送短信,数据库写入,部署到服务器,web收尾篇。
花狗Fdog
2021/05/06
4.1K0
Qt入门系列(二)
选中mainWindow.cpp右键->在Explor中显示->粘贴进来(显示包含的目录)
用户9831583
2022/06/16
2K0
Qt入门系列(二)
QT之Qml使用QSystemTrayIcon实现系统托盘
 QT中实现这一功能使用QSystemTrayIcon,它为应用程序在系统托盘中提供一个图标。现代操作系统通常在桌面上提供一个特殊区域,称为系统托盘或通知区域,长时间运行的应用程序可以在其中显示图标和短消息。
杨永贞
2022/05/11
2.8K0
QT之Qml使用QSystemTrayIcon实现系统托盘
用Qt写软件系列三:一个简单的系统工具之界面美化
前言      在上一篇中,我们基本上完成了主要功能的实现,剩下的一些导出、进程子模块信息等功能,留到后面再来慢慢实现。这一篇来讲述如何对主界面进行个性化的定制。Qt库提供的只是最基本的组件功能,使用
24K纯开源
2018/01/18
6.6K0
用Qt写软件系列三:一个简单的系统工具之界面美化
Qt入门系列(四)
新建一个class C++:ChoselevelScence,简称cs,继承QMainWIndow
用户9831583
2022/06/16
9610
Qt入门系列(四)
Qt Style Sheet实践(二):组合框QComboBox的定制
导读      组合框是一个重要且应用广泛的组件,一般由两个子组件组成:文本下拉单部分和按钮部分。在许多既需要用户选择、又需要用户手动输入的应用场景下,组合框能够很好的满足我们的需求。如我们经常使用的
24K纯开源
2018/01/18
8.1K0
Qt Style Sheet实践(二):组合框QComboBox的定制
Qt编写自定义控件35-GIF录屏控件
在平时的写作过程中,经常需要将一些操作动作和效果图截图成gif格式,使得涵盖的信息更全面更生动,有时候可以将整个操作过程和运行效果录制成MP4,但是文件体积比较大,而且很多网站不便于上传,基本上都支持gif动图,一般一个5秒左右的gif,800*600分辨率,可以很好的控制在500KB内,这样就比较完美的支持各大网站上传动图。
feiyangqingyun
2019/08/27
1.5K0
Qt编写自定义控件35-GIF录屏控件
【QT】:QMainWindow 窗口
Qt 中的菜单栏是通过 QMenuBar 这个类来实现的。一个主窗口最多只有一个菜单栏,位于主窗口顶部、主窗口标题栏下面。
IsLand1314
2025/02/18
1080
【QT】:QMainWindow 窗口
Qt学习之路_14(简易音乐播放器)
  这一节实现一个简易的音乐播放器,其音乐播放的核心功能是采用Qt支持的Phonon框架,该框架在前一篇博文Qt学习之路_13(简易俄罗斯方块) 中已经使用过了,在俄罗斯方块中主要是用来设置背景音乐和消行的声音的。这里用这个框架同样是用来播放,暂停等多媒体的各种控制功能,另外该框架可以自动获取音频文件的一些信息,这样我们在设计播放列表时可以获取这些信息,比如歌手名,专辑名,时长,文件名等等。程序中桌面歌词的实现是继承了QLabel类,然后使用3层文本显示,最上面一层采用渐进显示的方式来达到歌词播放的动态效果。
bear_fish
2018/09/20
2K0
Qt学习之路_14(简易音乐播放器)
Qt编写自定义控件68-IP地址输入框
这个IP地址输入框控件,估计写烂了,网上随便一搜索,保证一大堆,估计也是因为这个控件太容易了,非常适合新手练手,一般的思路都是用4个qlineedit控件拼起来,然后每个输入框设置正则表达式过滤只能输入3位数字,然后安装事件过滤器识别回车自动跳到下一个输入框。关于如何设置正则表达式过滤,这个可以搜索查到,本人也不大懂这个规则,貌似还有专门的书籍专门介绍正则表达式,可能这块非常强大。
feiyangqingyun
2019/10/16
2.1K0
Qt编写自定义控件68-IP地址输入框
Qt实战:云曦日历篇
自国务院印发《推进普惠金融发展规划(2016—2020年)》通知以来,各省、自治区、直辖市人民政府、国务院各部委各直属机构积极响应,认真贯彻执行,普惠金融发展已经进入了高潮阶段,各大互联网公司和高校紧跟时代潮流,推出了各种创新性产品和软件,该软件作为一款以培养兴趣,提高学生软件项目的编程项目能力为目的,所创建的一款实用性的软件,以日历为依托,创建了许多相关的特效,优美界面和天气查询、日程管理等实用性功能,且界面等均符合当下青少年的审美需求,是一款紧跟潮流的日历软件
灵彧
2022/10/31
1.5K0
Qt实战:云曦日历篇
PyQt5 入门
我的路径是:D:\ProgramData\Anaconda3\envs\cv\Lib\site-packages\qt5_applications\Qt\bin\designer.exe
Michael阿明
2022/05/10
1.5K0
PyQt5 入门
相关推荐
【QT】系统事件入门 -- 文件 QFile基础和示例
更多 >
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
查看详情【社区公告】 技术创作特训营有奖征文
本文部分代码块支持一键运行,欢迎体验
本文部分代码块支持一键运行,欢迎体验