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 ...
随机推荐
- JavaScript字符串与数组方法整理
字符串(String)的方法: 代码后面的都是返回值 var str = "atusdgafsvg"; var str1 = "123456789"; var ...
- window7环境下ZooKeeper的安装及运行
简介 ZooKeeper是一个分布式的,开放源码的分布式应用程序协调服务,是Google的Chubby一个开源的实现,是Hadoop和Hbase的重要组件.它是一个为分布式应用提供一致性服务的软件,提 ...
- GeoHash(Java实现)
package com.koubei.collect_script.demo; import java.util.ArrayList; import java.util.Arrays; import ...
- centos7 ping不通 name or service not known
最近打算为centos安装一个界面时,发现不能上网.ping www.baidu.com 报name or service not known. 原来网络配置没设好. 一.选择VMWare的NAT模式 ...
- Linux一键安装宝塔控制面板
Linux一键安装宝塔的命令行 yum install -y wget && wget -O install.sh http://download.bt.cn/install/inst ...
- WebGL绘制有宽度的线
WebGL中有宽度的线一直都是初学者的一道门槛,因为在windows系统中底层的渲染接口都是D3D提供的,所以无论你的lineWidth设置为多少,最终绘制出来的只有一像素.即使在移动端可以设置有宽度 ...
- 基础:新建个maven项目
首先在电脑上配置好Maven环境 第一步:在Eclipse中选择创建Maven Project Next Next Finish 创建好后项目结构如下: 第二步:讲项目转为Web项目,右键项目点击pr ...
- Redis的7个应用场景
一:缓存——热数据 热点数据(经常会被查询,但是不经常被修改或者删除的数据),首选是使用redis缓存,毕竟强大到冒泡的QPS和极强的稳定性不是所有类似工具都有的,而且相比于memcached还提供了 ...
- MySQL 千万级 数据库或大表优化
首先考虑如下因素: 1.数据的容量:1-3年内会大概多少条数据,每条数据大概多少字节: 2.数据项:是否有大字段,那些字段的值是否经常被更新: 3.数据查询SQL条件:哪些数据项的列名称经常出现在WH ...
- Android OpenSL ES 开发:Android OpenSL 录制 PCM 音频数据
一.实现说明 OpenSL ES的录音要比播放简单一些,在创建好引擎后,再创建好录音接口基本就可以录音了.在这里我们做的是流式录音,所以需要用至少2个buffer来缓存录制好的PCM数据,这里我们可以 ...