Qt显示Linux desktop natification气泡提示框
在现代Linux桌面环境上我们时常可以看到类似的消息框:

这些消息框常用在如下场景:
- 即时聊天软件的新消息
- 闹钟定时提示
- 电池电量提示
- 邮件消息
- 长耗时操作的完成提示
在freedesktop.org的规范中这种消息框被称为Desktop Notification,中文名我们形象得称其为“气泡框”。通过调用D-BUS服务org.freedesktop.Notifications提供的接口即可显示在桌面上。
所以我们先了解一下这个D-BUS服务。
org.freedesktop.Notifications概览
一个气泡框消息通常会包含如下的属性:
| 名称 | 说明 |
|---|---|
| Application Name | 标示发送消息的程序,最好使用程序全名 |
| Replaces ID | 可选的消息ID,服务器通过id控制消息框的渲染,通常不用关注 |
| Icon | 显示在气泡框上的图标 |
| Summary | 标题,只能显示一行,叫title应该更合适 |
| Body | 消息体,支持部分HTML标签;<b></b>;<i></i>;<u></u>;<a></a>;<img src=... alt=...> |
| Actions | 显示一些按钮或者菜单(QAction),不过这一功能通常未被实现 |
| Hints | 为消息体提供的额外数据,比如显示在屏幕的位置(x,y坐标) |
| Expiration Timeout | 气泡框显示的时长,单位毫秒;指定为-1时行为取决于实现;为0时气泡框将一直显示在桌面上直到用户点击 |
其中Icon和Hints中的image_path必须为本地绝对路径或者file://开头的文件URL。另外使用桌面环境预定义图标的名字也是可以的。
气泡框还有三个紧急程度可供选择:
| 名称 | 值 | 说明 |
|---|---|---|
| Low | 0 | 默认值,可以设置如何显示,应该设置一个合理的显示时间以便气泡框可以隐藏退出 |
| Normal | 1 | 同low |
| Critical | 2 | 代表重要通知,不应该自动过期隐藏 |
所有的气泡框消息请求都是异步的,通常构造请求并发送后用户就可以不再关心后续的信息,如果有特殊需要则可以自定义处理org.freedesktop.Notifications发送的信号。
得益于freedesktop.org的标准规范,包括KDE,GNOME,XFCE4在内的许多桌面环境都提供了对Desktop Notification的支持,虽然外观上可能存在一些差异但是创建气泡框的方法是一样的。
不过不用担心,我们不会直接去使用D-BUS,因为已经有简化的现成方案可供选择了。下面就让我们一起看看这些方案。
方案一:调用外部命令
可能你已经知道了,我要介绍的命令就是notify-send。
notify-send几乎被所有的桌面环境和发行版支持,它依赖于后面会介绍的libnotify和glib,如果你的系统上没有安装可以使用如下命令进行安装:
debian/Ubuntu:
sudo apt install libnotify-bin
Arch Linux:
sudo pacman -S libnotify
安装后可以用如下命令显示气泡框:
# notify-send title body [options]
notify-send test 'This is a desktop Notification test.' -t 10000
-t参数设置超时时间。效果如下:

具体的参数可以参考这里:https://ss64.com/bash/notify-send.html
方案二:通过编程方式实现
在Qt代码中调用外部命令就可以显示气泡框,然而这种方式不够灵活,所以我们需要使用前面提到的libnotify在我们的代码里生成并显示气泡框。
libnotify对各个语言都提供了binding,可以参考这里。
这里我们选择使用golang的binding:
package main
import ("github.com/mqu/go-notify")
func main() {
notify.Init("Hello world")
hello := notify.NotificationNew("Hello World!", "This is an example notification.","dialog-information")
hello.SetTimeout(5000)
hello.Show()
}
上面的代码将会显示一个可以在桌面停留5s的气泡框:

不过如果每次都要使用一大串代码才能显示消息的话必然是低效的,而且需要换算时间至毫秒,所以我写了一个帮助函数在notify.go:
// ShowNotification 显示org.freedesktop.Notifications气泡消息框
// duration == -1时使用默认delay
// duration == 0表示不设置超时,desktop notification将会一直显示
func ShowNotification(title, text, image string, delay time.Duration) {
var notifyDelay int32
if delay == -1 {
notifyDelay = duration2millisecond(defaultNotifyDelay)
} else {
notifyDelay = duration2millisecond(delay)
// 不合法值(包括duration不足1ms),使用默认值进行替换
if notifyDelay == -1 {
notifyDelay = duration2millisecond(defaultNotifyDelay)
}
}
libnotify.Init(applicationName)
notify := libnotify.NotificationNew(title, text, image)
if notify == nil {
fmt.Fprintf(os.Stderr, "Unable to create a new notification\n")
return
}
notify.SetTimeout(notifyDelay)
notify.Show()
}
// duration2millisecond 将time.Duration转换成millisecond
// duration不足1ms将返回-1
func duration2millisecond(duration time.Duration) int32 {
res := int32(duration / time.Millisecond)
if res < 0 {
return -1
}
return res
}
首先将时间值转换成毫秒数,如果太小或者不合法就使用默认的停留时间。applicationName是程序的完整名称。
因为气泡框消息是异步的,所以在调用了Show()之后函数就会返回,后续操作xwindows都会帮我们处理,所以这个函数调用之后是立刻返回的,不会阻塞Qt的gui事件循环,可以放心的使用:
// download something success
ShowNotification("下载", "文件下载完成", "dialog-information", 5*time.Second)

这样我们也可以轻松地在我们的Qt程序中使用气泡消息框了。
参考:
https://developer.gnome.org/notification-spec/
Qt显示Linux desktop natification气泡提示框的更多相关文章
- Arc Engine 中添加气泡提示框
一.在ArcMap中的定位操作 已知若干点的经纬度坐标,要求在地图中进行定位: 1.通过Tool >Add X Y data 定位点,注意选择地理坐标系下的wgs 1984坐标系: 2.定位后的 ...
- iOS 灵活,简易,扩展性强的气泡提示框LFBubbleView(含源码)
一.效果图 二.使用方法 使用简单,4行代码集成. _bubbleView = [[LFBubbleView alloc] initWithFrame:CGRectMake(, , , )]; _bu ...
- 写入cookie后只显示一次的DIV提示框代码
<script type="text/javascript"> function cookiesave(n, v, mins, dn, path){ if(n) { i ...
- jqury关于cooke的操作写入cookie后只显示一次的DIV提示框代码
有时候当用户登录系统后,需要给用户弹出提示框,但是不需要总是弹出来,在这里加入访问cookie来判断是否弹出过提示框,如果弹出过那么保存cookie,下次根据cookie是否存在来判断是否弹出 < ...
- css实现气泡提示框三角及css中drop-shadow的使用
css 做一个弹出气泡,样式怎么设计? 难点: 要实现白色三角型,可以在伪元素before和after上设置一个黑.一个白三角形,白三角形会挡住黑的,从而实现. &::before, & ...
- CSS气泡提示框 可自定义配置箭头
在线演示 本地下载
- qt之透明提示框(模拟qq) (非常漂亮)
Qt实现类似QQ的登录失败的提示框,主要涉及窗口透明并添加关闭按钮,以及图标和信息的显示等. 直接上代码: #include "error_widget.h" ErrorWidge ...
- JS使用cookie实现DIV提示框只显示一次的方法
本文实例讲述了JS使用cookie实现DIV提示框只显示一次的方法.分享给大家供大家参考,具体如下: 这里运用JavaScript的cookie技术,控制网页上的提示DIV只显示一次,也就是当用户是第 ...
- EasyUI-Tooltip(提示框)学习
引子: if($("#BLUETOOTH_a")){ $("#BLUETOOTH_a").tooltip({ position: 'right', conten ...
随机推荐
- linux操作命令之帮助命令
一.man命令的帮助: man 命令名 获取指定命令的帮助 例如man ls 查看ls的帮助 man man可以看到man有8个级别的man帮助命令使用场景 1.查看命令的帮助 2.查看可被内核调用的 ...
- tag cloud的相关资料
http://reverland.org/python/2013/01/28/visualize-your-shell-history/ https://github.com/reverland/sc ...
- VUE插件大总结
UI组件 element - 饿了么出品的Vue2的web UI工具套件 Vux - 基于Vue和WeUI的组件库 mint-ui - Vue 2的移动UI元素 iview - 基于 Vuejs 的开 ...
- 【二代示波器教程】第14章 uCOS-III操作系统版本二代示波器实现
第14章 uCOS-III操作系统版本二代示波器实现 本章教程为大家讲解uCOS-III操作系统版本的二代示波器实现.主要讲解RTOS设计框架,即各个任务实现的功能,任务间的通信方案选择,任 ...
- 高性能网络服务器编程:为什么linux下epoll是最好,Netty要比NIO.2好?
基本的IO编程过程(包括网络IO和文件IO)是,打开文件描述符(windows是handler,java是stream或channel),多路捕获(Multiplexe,即select和poll和ep ...
- [Swift]LeetCode648. 单词替换 | Replace Words
In English, we have a concept called root, which can be followed by some other words to form another ...
- 一个简单IP防刷工具类, x秒内最多允许y次单ip操作
IP防刷,也就是在短时间内有大量相同ip的请求,可能是恶意的,也可能是超出业务范围的.总之,我们需要杜绝短时间内大量请求的问题,怎么处理? 其实这个问题,真的是太常见和太简单了,但是真正来做的时候,可 ...
- 基于IPV6的数据包分析(更新拓扑加入了linux主机和抓取133icmp包)(第十三组)
1.拓扑图 2.配置ipv6地址,在拓扑图上对应位置标有对应网段,所在网段的端口按照网段配置,下图以r4为例 3.配置路由表,由于静态路由还要敲ip很麻烦所以使用ospf协议,下图为ospf配置以r5 ...
- RSA算法原理——(3)RSA加解密过程及公式论证
上期(RSA简介及基础数论知识)为大家介绍了:互质.欧拉函数.欧拉定理.模反元素 这四个数论的知识点,而这四个知识点是理解RSA加密算法的基石,忘了的同学可以快速的回顾一遍. 一.目前常见加密算法简介 ...
- BBS论坛(三十三)
33.celery实现邮件异步发送 (1)task.py pip install celery redis from celery import Celery from flask import Fl ...