工具提示即 Tool Tip,当用户把鼠标移动到某个UI对象上并悬停片刻,就会出现一个“短小精悍”的窗口,显示一些说明性文本。一般就是功能描述,让用户知道这个XX是干啥用的。

在 Qt 中使用工具提示最方便的做法是直接用 QWidget 类的成员方法:setToolTip。从 QWidget 类派生的组件都可以用,直接设置文本内容即可,用起来很 666。

下面举个例子:示例窗口上有三个单选按钮(QRadioButton),分别为它们设置工具提示。

#include <qapplication.h>
#include <qwidget.h>
#include <qboxlayout.h>
#include <qradiobutton.h>
#include <qlabel.h> int main(int argc, char* argv[])
{
QApplication app(argc, argv); // 窗口
QWidget *window = new QWidget;
// 大小和标题
window->setWindowTitle("2023劲爆游戏盲盒");
window->resize(300, 280);
// 布局
QVBoxLayout* layout = new QVBoxLayout;
window->setLayout(layout);
// 在布局内放些组件
// 1、标签
QLabel *lbTxt = new QLabel(window);
lbTxt->setText("请选择一个分组开箱,祝您好运。");
layout->addWidget(lbTxt);
// 2、三个单选按钮
QRadioButton* opt1=new QRadioButton("霸王组", window);
QRadioButton *opt2 = new QRadioButton("受虐组", window);
QRadioButton *opt3 = new QRadioButton("狗粮组", window);
layout->addWidget(opt1);
layout->addWidget(opt2);
layout->addWidget(opt3);
layout->addStretch(1); // 给三个单选按钮设置工具提示
opt1->setToolTip("霸王组的游戏玩得特别有自信,玩家的战斗力最大化,对手的战斗力弱得像小鸡一样,一打一个爽,一直打一直爽。");
opt2->setToolTip("受虐组的游戏玩起来比较惨,玩家的战斗力被严重削弱,对手的力量无比强大,基本被按在水泥地板上摩擦。该组游戏难度大到吓死人。");
opt3->setToolTip("狗粮组游戏比较温馨,玩家可以自由组CP,然后拼命发狗粮。哪一组CP被别人发的糖给甜死了就算出局。"); // 显示窗口
window->showNormal(); return QApplication::exec();
}

这是最基本的工具提示,没什么可折腾的,设置字符串就行。看看效果。

下面说说另一种复杂些的方法。QToolTip 类公开一组静态成员,可以用于手动控制工具提示。例如,你可以:

showText:显示工具提示。这个用得较多;
hideText:隐藏工具提示。这个一般不需要调用,毕竟你鼠标移出目标组件的区域后就会自动隐藏。
下面咱们还是用例子说事。例子程序的窗口中水平躺了两个按钮,然后连接按钮的 clicked 信号,通过调用 showText 方法手动显示工具提示。
#include <QApplication>
#include <QWidget>
#include <QToolTip>
#include <QPushButton>
#include <QHBoxLayout> class MyWindow : public QWidget
{
public:
MyWindow(); private:
QHBoxLayout* layout;
QPushButton* btnA;
QPushButton* btnB;
// 两个slots
void onAClicked();
void onBClicked();
}; /***************************************************/ MyWindow::MyWindow()
:QWidget::QWidget(nullptr)
{
// 初始化布局
layout = new QHBoxLayout;
setLayout(layout);
// 弄两个按钮
btnA = new QPushButton("按钮 1", this);
btnB = new QPushButton("按钮 2", this);
layout->addWidget(btnA, 0, Qt::AlignTop);
layout->addWidget(btnB, 0, Qt::AlignTop);
// 连接一下clicked信号
connect(btnA, &QPushButton::clicked, this, &MyWindow::onAClicked);
connect(btnB, &QPushButton::clicked, this, &MyWindow::onBClicked);
}

由于我这个类没有明确声明信号等东东,所以不加 Q_OBJECT 宏也没问题。如果加 Q_OBJECT 宏,这个类的定义最好放头文件里,这样就不必手动执行 MOC。

接下来咱们重点实现响应 clicked 信号的那两个方法。

void MyWindow::onAClicked()
{
// 获取按钮的矩形区域坐标
QPushButton* _b = static_cast<QPushButton*>(sender());
QRect rect = _b->rect();
// 左下角坐标
QPoint lbpoint = rect.bottomLeft();
// 转换为全局坐标
QPoint gpos = _b->mapToGlobal(lbpoint);
// 手动显示提示信息
QToolTip::showText(gpos, "单击它,实现梦想");
} void MyWindow::onBClicked()
{
auto b = static_cast<QPushButton*>(sender());
// 获取按钮的矩形区域
QRect rect = b->rect();
// 左下角
QPoint p1 = rect.bottomLeft();
// 映射全局坐标
p1 = b->mapToGlobal(p1);
// 显示工具提示
QToolTip::showText(p1, "单击它,放弃梦想");
}

两个方法的逻辑是一样的。首先通过 sender() 方法可以知道正在发送信号的对象,这里就是按钮。然后得到按钮的矩形区域的左下角坐标。对的,我就是想让工具提示显示在按钮左下角。由于工具提示实际上是一个无边框的顶层窗口(内部用 QLabel 实现的),所以要用相对于屏幕的坐标,调用 mapToGlobal 方法可以将相对坐标(按钮相对于程序窗口)转换为屏幕坐标。

最后,一句 showText 调用显示提示。

注意,咱们这里是单击按钮后才会显示工具提示的,鼠标移上去是不会出现提示的。毕竟咱们手动触发了。

要单击按钮之后才显示工具提示,明显这做法是不合理的,所以,QToolTip 类更合理的用法是 ToolTip 事件。对于自定义的组件类,可以重写 event 方法,然后分析事件类型是否为 ToolTip,如果是就用 QToolTip::showText 显示工具提示。不过这种做法还是不怎么好用,总不能只为了一个工具提示就把常用的组件都派生一遍吧。所以,比较好的方法是使用【事件过滤器】,被过滤者(窗口中用到的各组件)安装过滤器;而当前窗口类重写 eventFilter 方法,使自己变成事件过滤器。这样,在窗口类中就可以拦截各个组件的事件并做出处理了。

下面举例老周用 Python 来写,只是换种语言换个口味而已,知识点是不变的哟。

from PySide6.QtCore import *
from PySide6.QtGui import *
from PySide6.QtWidgets import * # 自定义窗口类
class MyWindow(QWidget):
def __init__(self):
# 调用基类的构造函数
super().__init__()
# 设置布局
layout = QFormLayout()
self.setLayout(layout)
# 表单的第一行
self.txtName = QLineEdit(self)
layout.addRow("用户名:", self.txtName)
# 表单的第二行
self.txtPass = QLineEdit(self)
layout.addRow("密码:", self.txtPass)
# 这个输入框需要显示掩码
self.txtPass.setEchoMode(QLineEdit.EchoMode.Password)
# 表单的第三行,CheckBox控件
self.ckbRemember = QCheckBox(self)
self.ckbRemember.setText("记住我")
layout.addRow(self.ckbRemember)
# 表单第四行,两个按钮
# 这两个按钮需要子布局,让它们躺平
btnLayout = QHBoxLayout()
self.btnLog = QPushButton("确定", self)
btnLayout.addWidget(self.btnLog)
self.btnExit = QPushButton("退出", self)
btnLayout.addWidget(self.btnExit)
layout.addRow(btnLayout)
# 为需要的组件安装事件过滤器
self.txtName.installEventFilter(self)
self.txtPass.installEventFilter(self)
self.btnLog.installEventFilter(self)
self.btnExit.installEventFilter(self)
self.ckbRemember.installEventFilter(self) # 当前类重写这个方法,成为事件过滤器
def eventFilter(self, watched: QObject, event: QEvent) -> bool:
# 判断事件类型
if event.type() == QEvent.Type.ToolTip:
helpevent: QHelpEvent = event
# 给各组件设置工具提示
tip = 'what the Fxxk'
if watched is self.txtName:
tip = '请输入你的大名'
if watched is self.txtPass:
tip = '请输入密码'
if watched is self.ckbRemember:
tip = '选中这个后,下次登录不用再输密码了'
if watched is self.btnLog:
tip = '点这里,确认登录'
if watched is self.btnExit:
tip = '不登录了,直接退出'
# 显示工具提示
QToolTip.showText(
helpevent.globalPos(), # 当前鼠标的全局坐标
tip
)
# 调用基类成员
return super().eventFilter(watched, event)

窗口使用 QFormLayout 布局,表单,类似 HTML Form 的布局。两个 QLineEdit 组件,用来输入用户名和密码;两 QPushButton 组件,即普通按钮;还有一个复选框 QCheckBox。

依次调用这些组件的 installEventFilter 方法,安装过滤器,方法参数就是对过滤器实例的引用。在 MyWindow 类中,它重写了 eventFilter 方法,说明 MyWindow 类自身已经成为事件过滤器了。所以当前实例 self 可传递给 installEventFilter 方法。

eventFilter 方法的声明如下:

bool QObject::eventFilter(QObject *watched, QEvent *event)

watched 参数引用的就是被拦截的对象。比如,如果 btnLog 的 ToolTip 事件被拦截,那么 watched 参数引用的就是 btnLog。event 参数是 QEvent 类的派生类,提供与事件有关的数据,不同事件下它的类型不同。对于 ToolTip 事件,其类型是 QHelpEvent。该类提供了显示工具提示所需的全局坐标。

对于 ToolTip 事件,相关的事件类是 QHelpEvent。可以从它的 globalPos 方法获得当前鼠标的屏幕坐标。调用 showText 方法时,第一个参数就是传递工具提示应该出现的位置。当然,这是全局坐标。第二个参数就是提示的文本,剩下的参数可以忽略。

实例化并显示自定义窗口,启动应用程序的主循环。

if __name__ == "__main__":
# 初始化应用程序
app = QApplication()
# 初始化窗口
win = MyWindow()
win.setWindowTitle("试玩")
win.resize(240, 130)
win.show()
# 进入主循环
QApplication.exec()

运行的效果如下面的超清动图所示。

最后部分咱们讨论一下工具提示的调色板问题。QToolTip 允许以调色板的方式设置提示的背景色和前景色(文本颜色)。直接看例子:

int main(int argc, char* argv[])
{
QApplication app(argc, argv);// 获取工具提示的现有调色板
QPalette pal = QToolTip::palette();
// 修改背景色
pal.setColor(
QPalette::Inactive,
QPalette::ToolTipBase,
QColor("darkblue")
);
// 修改文本颜色
pal.setColor(
QPalette::Inactive,
QPalette::ToolTipText,
QColor("lightyellow")
);
// 重新设置调色板
QToolTip::setPalette(pal); // 窗口
QWidget* window = new QWidget;
window->setWindowTitle("自定义ToolTip颜色");
window->resize(250, 100);
// 布局
QHBoxLayout *layout = new QHBoxLayout;
window->setLayout(layout);
// 两个按钮
QPushButton *btn1, *btn2;
btn1 = new QPushButton("回到过去", window);
btn2 = new QPushButton("看看未来", window);
layout->addWidget(btn1);
layout->addWidget(btn2);
// 为按钮设置提示
btn1->setToolTip("一键触发穿越之旅");
btn2->setToolTip("一键改变人生");
// 显示窗口
window->show(); // 进入主循环
return QApplication::exec();
}

代码是没有问题的,但很多同学可能遇到运行之后没有效果的问题。就像这样:

很多大伙伴们可能还找不到解决方案。其实这事是主题造成的,Windows 上默认使用 WindowsVista 主题,我们换一个主题就行了,比如,换成 Windows 主题。如果你不知道当前环境下支持哪些主题,可以调试输出一下 QStyleFactory::keys 方法的返回结果。

qDebug() << QStyleFactory::keys();

得到的输出如下:

QList("windowsvista", "Windows", "Fusion")

除了 Windowsvista,另外两个随便选,都可以。

咱们修改一下应用程序的主题,在 app 变量上调用。

QApplication app(argc, argv);
// 改变主题
app.setStyle("Fusion");

再运行一下看看,效果就有了。

好了,今天的话题就聊到这儿了。

【Qt6】工具提示以及调色板设置的更多相关文章

  1. 根据 Power BI Desktop(预览版)中的报表页创建工具提示

    根据 Power BI Desktop 中创建的报表页,可创建直观丰富的报表工具提示,这些提示在你将鼠标悬停在视觉对象上时显示. 通过创建用作工具提示的报表页,使自定义工具提示包含视觉对象.图像以及在 ...

  2. QT中QToolTip样式设置的两种方式

    方式一 使用样式表设置 ui.label->setStyleSheet("QToolTip{border:1px solid rgb(118, 118, 118); backgroun ...

  3. 数据可视化之powerBI基础(四)深入了解PowerBI的工具提示功能

    https://zhuanlan.zhihu.com/p/36804592 在PowerBI上个月的更新中,增加了工具提示功能,这项功能允许您将自己的可视化作品放置到工具提示中,通过鼠标悬停的方式来展 ...

  4. html初学者了解的笔记02

    一.Html简介 HTML 是一种标记语言 忽略大小写,语法宽松 使用 HTML 标记和元素,可以: 控制页面和内容的外观 发布联机文档 使用 HTML 文档中插入的链接检索联机信息 创建联机表单,收 ...

  5. HTML的总结

    一.Html简介    HTML 是一种标记语言       忽略大小写,语法宽松    使用 HTML 标记和元素,可以:       控制页面和内容的外观       发布联机文档       使 ...

  6. Qt4.7文档翻译:Qt样式单参考,Qt Style Sheets Reference(超长,超全)

    内容目录 Qt样式单参考 可进行样式设置的部件列表 属性列表 图标列表 属性类型列表 伪状态列表 子控件列表 Qt样式单参考 Qt样式单支持各种属性.伪状态和子控件,这样使得妳能够自行设计部件的外观. ...

  7. VC常用小知识

    (1) 如何通过代码获得应用程序主窗口的 指针?主窗口的 指针保存在CWinThread::m_pMainWnd中,调用AfxGetMainWnd实现.AfxGetMainWnd() ->Sho ...

  8. 微软Power BI报表服务器学习总览

    今天,微软宣布了8月更新Power BI Report Server!此版本包含一些新功能,包括一些备受期待的项目,如报表主题,条件格式改进和报表页面工具提示. 报告 报告主题 用于触发操作的按钮 组 ...

  9. Windows 窗体消息大全(速查)

    Windows窗口消息大全,全不全自己撸 通用窗口消息 WM_NULL:--------->空消息,可检测程序是否有响应等 WM_CREATE:--------->新建一个窗口 WM_DE ...

  10. Bootstrap简易使用指南

    1.框架 1.1全局样式 使用HTML5的doctype,scaffolding.less中定义全局样式,从2开始使用normalize.css,并使用reset.less进行简化 1.2默认栅格系统 ...

随机推荐

  1. Python-3.10安装步骤

    下载地址: https://www.python.org/ftp/python/3.10.4/python-3.10.4-amd64.exe 安装:   C:\Users\liujun>pyth ...

  2. Spring源码:Bean生命周期(终章)

    前言 本系列前面讲解了Spring的bean定义.bean实例化.bean初始化等生命周期.这些步骤使我们能够了解bean从创建到准备好使用所经历的过程.但是,除了这些步骤,bean的销毁也是非常重要 ...

  3. Vuex modules 中active相互调用

    大中型项目中使用vuex进行状态管理时,经常会按模块分割到不同的module中去,而操作中难免有模块中的active相互调用的情况,然而有时也会出现一些问题,这里顺便记录下 store目录结构 在us ...

  4. Go 开源库运行时依赖注入框架 Dependency injection

    Dependency injection 一个Go编程语言的运行依赖注入库.依赖注入是更广泛的控制反转技术的一种形式.它用于增加程序的模块化并使其具有可扩展性. 实例展示(High API): typ ...

  5. Atcoder-AGC033C

    看到这道题,是个博弈论,没见过树上的,于是想到在数列里的博弈论,又联想到树的特殊形式----链. 于是我们来讨论一下链的情况(对于没有硬币的点,我们就视为它被删掉了): 讨论链的情况 发现若是选择两端 ...

  6. 识别一切模型RAM(Recognize Anything Model)及其前身 Tag2Text 论文解读

    总览 大家好,我是卷了又没卷,薛定谔的卷的AI算法工程师「陈城南」~ 担任某大厂的算法工程师,带来最新的前沿AI知识和工具,欢迎大家交流~ 继MetaAI 的 SAM后,OPPO 研究院发布识别一切模 ...

  7. IDEA2021.3.3使用

    下载文件 :ja-netfilter-all-2021.3.3 激活码 : P29GTZBZ3Y-eyJsaWNlbnNlSWQiOiJQMjlHVFpCWjNZIiwibGljZW5zZWVOYW1 ...

  8. Selenium:设置元素等待、上传文件、下载文件

    前言:在工作和学习selenium自动化过程中记录学习知识点,深化知识点 1. 设置元素等待 元素定位之元素等待-- WebDriver提供了两种类型的等待:显示等待和隐式等待. 1.1 显示等待 显 ...

  9. 前端学习 C 语言 —— GDB调试器

    GDB调试器 我们在讲指针时用 GDB 调试段错误. 本篇将详细介绍 gdb 的最常用命令.日志记录.检测点,最后介绍如何用 gdb 调试进程以及用gdb 调试一个开源项目的调试版本 -- glmar ...

  10. JAVA代码下载TXT文件(本地和服务器上的代码都可以)

    // 读取服务器文件内容(TXT文件测试可以) public static List<String> showTxt(String filePath) throws IOException ...