在Qt中想要为QAbstractItemView中长度不够而使得内容被截断的项显示ToolTip,Qt官网有一篇文章介绍使用事件过滤器来显示太长的项,但是没有涵盖图标的情况、显示列头项太长的情况等等,这里做了下修改,以符合现在所需。

环境:Qt 5.1.0
atooltipper.h

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
 
#ifndef ATOOLTIPPER_H
#define ATOOLTIPPER_H

#include <QObject>

class AToolTipper : public QObject
{
    Q_OBJECT
public:
    explicit AToolTipper(QObject *parent = 0);
    
    virtual bool eventFilter(QObject *, QEvent *);

protected:
    bool headerViewEventFilter(QObject *, QEvent *);
};

#endif // ATOOLTIPPER_H

atooltipper.cpp

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
 
#include "atooltipper.h"
#include <QHelpEvent>
#include <QAbstractItemView>
#include <QHeaderView>
#include <QTreeView>
#include <QTableView>
#include <QToolTip>

AToolTipper::AToolTipper(QObject *parent) :
    QObject(parent)
{
}

bool AToolTipper::eventFilter(QObject *obj, QEvent *event)
{
    if (event->type() == QEvent::ToolTip)
    {
        QAbstractItemView *view = qobject_cast<QAbstractItemView*>(obj->parent());
        if (!view)
        {
            return false;
        }

QHeaderView *headerView = qobject_cast<QHeaderView*>(view);
        if (headerView)
        {
            return headerViewEventFilter(obj, event);
        }

QHelpEvent *helpEvent = static_cast<QHelpEvent*>(event);
        QPoint pos = helpEvent->pos();
        QModelIndex index = view->indexAt(pos);
        if (!index.isValid())
        {
            return false;
        }

QString itemText = view->model()->data(index).toString();

// 图标处理
        QSize iconSize(0, 0);
        QIcon icon = view->model()->data(index, Qt::DecorationRole).value<QIcon>();
        if (!icon.isNull())
        {
            QList<QSize> listSize = icon.availableSizes();
            if (listSize.size() > 0)
            {
                iconSize.setWidth(listSize.at(0).width());
                iconSize.setHeight(listSize.at(0).height());
            }
        }

// 计算列头高度
        int headerHeight = 0;
        int headerWidth = 0;
        QTreeView *treeView = qobject_cast<QTreeView*>(view);
        if (treeView)
        {
            headerHeight = treeView->header()->height();
        }
        else
        {
            QTableView *tableView = qobject_cast<QTableView*>(view);
            if (tableView)
            {
                headerHeight = tableView->horizontalHeader()->height();
                headerWidth = tableView->verticalHeader()->width();
            }
        }

// 文本边距
        const int textMargin = view->style()->pixelMetric(QStyle::PM_FocusFrameHMargin) + 1;
        const int iconMargin = iconSize.width() > 0 ? (view->style()->pixelMetric(QStyle::PM_FocusFrameHMargin) + 1) : 0;
        QRect rect = view->visualRect(index);
        QRect textRect = rect.adjusted(textMargin + iconSize.width() + iconMargin * 2, 0, -textMargin, 0); //实际可用矩形

QFontMetrics fm(view->font());
        int flags = view->model()->data(index, Qt::TextAlignmentRole).toInt();
        QSize itemTextSize = fm.boundingRect(textRect, flags | Qt::TextLongestVariant | Qt::TextWordWrap, itemText).size();

if ((itemTextSize.width() > textRect.width() || itemTextSize.height() > textRect.height()) && !itemText.isEmpty())
        {
            // 指定tip的限定矩形
            rect.adjust(headerWidth, headerHeight, headerWidth, headerHeight);
            QToolTip::showText(helpEvent->globalPos(), itemText, view, rect);
        }
        else
        {
            QToolTip::hideText();
        }
        return true;
    }

return false;
}

bool AToolTipper::headerViewEventFilter(QObject *obj, QEvent *event)
{
    if (event->type() == QEvent::ToolTip)
    {
        QHeaderView *headerView = qobject_cast<QHeaderView*>(obj->parent());
        if (!headerView)
        {
            return false;
        }

QHelpEvent *helpEvent = static_cast<QHelpEvent*>(event);
        QPoint pos = helpEvent->pos();
        int index = headerView->logicalIndexAt(pos);
        if (index < 0)
        {
            return false;
        }

QString itemText = headerView->model()->headerData(index, headerView->orientation()).toString();
        const int textMargin = headerView->style()->pixelMetric(QStyle::PM_FocusFrameHMargin) + 1;
        int rectWidth = headerView->sectionSize(index) - textMargin * 2;
        int rectHeight = headerView->sizeHint().height();

QFontMetrics fm(headerView->font());        
        int flag = headerView->model()->headerData(index, headerView->orientation(), Qt::TextAlignmentRole).toInt();
        QSize itemTextSize = fm.size(flag, itemText);
        if ((itemTextSize.width() > rectWidth || itemTextSize.height() > rectHeight) && !itemText.isEmpty())
        {
            QToolTip::showText(helpEvent->globalPos(), itemText, headerView);
        }
        else
        {
            QToolTip::hideText();
        }
        return true;
    }

return false;
}

使用示例:

1
2
 
tableView->viewport()->installEventFilter(new AToolTipper(tableView));
tableView->horizontalHeader()->viewport()->installEventFilter(new AToolTipper(tableView->horizontalHeader()));

效果图:

参考资料:
1.Show_tooltips_for_long_entries_of_your_custom_model http://qt-project.org/wiki/Show_tooltips_for_long_entries_of_your_custom_model
2.Tooltips for truncated items in a QTreeView http://www.mimec.org/node/337

http://blog.csdn.net/akof1314/article/details/14504747

QAbstractItemView为截断的项显示ToolTip(使用事件过滤)的更多相关文章

  1. QAbstractItemView为截断的项显示ToolTip(在eventFilter函数里覆盖QEvent::ToolTip事件)

    在Qt中想要为QAbstractItemView中长度不够而使得内容被截断的项显示ToolTip,Qt官网有一篇文章介绍使用事件过滤器来显示太长的项,但是没有涵盖图标的情况.显示列头项太长的情况等等, ...

  2. css截断长文本显示

    实现 截断长文本显示处理,以前是通过后台的截取,但这种方法容易丢失数据,不利于SEO. 而通过前端css的截断,则灵活多变,可统一运用与整个网站. 这项技术主要运用了text-overflow属性,这 ...

  3. 在Winfrom 中,如何实现combox 的列表自动显示ToolTip提示 ?

    //带ToolTip的combox类文件 public class ComboBoxWithTooltip : ComboBox { //tipProperty为显示ToolTip文本的数据源的属性 ...

  4. C++ CEF 浏览器中显示 Tooltip(标签中的 title 属性)

    在 Windows 中将 CEF 集成到 C++ 客户端以后,默认是无法显示 tooltip 的,比如图片标签中的 title 属性. 实现的方式其实很简单,按下面的步骤操作就可以: 创建一个文本文件 ...

  5. 【UWP】仅在TextBlock文本溢出时显示Tooltip

    前言 这是我今天在回答SO问题时偶然遇到的,觉得可能还比较通用,就记录下来以供参考. 通常,我们使用ToolTip最简单的方式是这样: <TextBlock Text="Test&qu ...

  6. dotnet ef执行报错, VS 2019发布时配置项中的Entity Framework迁移项显示不出来

    VS 2019发布时配置项中的Entity Framework迁移项显示不出来 dotnet ef dbcontext list --json “无法执行,因为找不到指定的命令或文件.可能的原因包括: ...

  7. WPF drag过程中显示ToolTip.

    原文:WPF drag过程中显示ToolTip. 在drag/drop过程中,我们在判断出over的元素上是否可以接受drag的东西之后,通常是通过鼠标的样式简单告诉用户这个元素不接受现在drag的内 ...

  8. ListView控件的列表项的文字不满一行的时候,如何实现点击该列表项的空白区域仍可触发列表项的点击事件

    今天在做Demo的过程中,使用到了ListView.然而在实现过程中,发现一个出现了一个问题:只能点击列表项的文字区域可以触发点击事件,而点击列表项的空白区域无法触发点击事件. 如下图: listit ...

  9. NGUI---使用脚本控制聊天系统的内容显示,输入事件交互

    在我的笔记Unity3D里面之 简单聊天系统一 里面已经介绍怎么创建聊天系统的背景.给聊天系统添加滚动条,设置Anchor锚点.以及设计聊天系统的输入框. 效果图如下所示: 现在我们要做的就是使用脚本 ...

随机推荐

  1. JUnit中@Test的运行顺序

    原文链接: Test execution order 原文日期: 2012年12月06日 翻译日期: 2014年10月16日 翻译人员: 百里马 依照设计,Junit不指定test方法的运行顺序. 到 ...

  2. 图解linux启动过程

    概述 watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvWUVZVUFOR0VO/font/5a6L5L2T/fontsize/400/fill/I0JBQkF ...

  3. win10下安装docker步骤(一)

    一.启用Hyper-V 打开控制面板 - 程序和功能 - 启用或关闭Windows功能,勾选Hyper-V,然后点击确定即可,如图: 请注意电脑默认的Hyper-V虚拟机监控程序是不能进行勾选的,需要 ...

  4. 【Codeforces Round #438 A】Bark to Unlock

    [链接]h在这里写链接 [题意] 在这里写题意 [题解] 枚举它是在连接处,还是就是整个字符串就好. [错的次数] 0 [反思] 在这了写反思 [代码] #include <bits/stdc+ ...

  5. dotnet core 通过修改文件头的方式隐藏控制台窗口

    原文:dotnet core 通过修改文件头的方式隐藏控制台窗口 在带界面的 dotnet core 程序运行的时候就会出现一个控制台窗口,本文告诉大家使用最简单方法去隐藏控制台窗口. 最近在使用 A ...

  6. 将字符串转换成xml并取得对应的值

    如数据库中有一个字段保存了xml格式的一串字符串: <?xml version="1.0" encoding="utf-16"?><Array ...

  7. c语言学习笔记(3)——输入输出

    一.基本的输入和输出函数的用法 printf()  //屏幕输出 用法: (1)printf("字符串\n"); (2)printf("输出控制符", 输出参数 ...

  8. echarts 堆叠折线

    option = { title: { text: '折线图堆叠' }, tooltip: { trigger: 'axis' }, legend: { data:['邮件营销','联盟广告','视频 ...

  9. 签署 Centennial Program Addendum,使用 Desktop Bridge 将 Win32 应用转制成 UWP

    原文 签署 Centennial Program Addendum,使用 Desktop Bridge 将 Win32 应用转制成 UWP 能上架 Windows 应用商店的并不一定必须是 UWP 应 ...

  10. sqlplus 上下工具

    http://yunpan.cn/QNXXpjP9aBy6v 訪问password 420b 想在Unix.Linux环境下使用sqlplus,像在win以下一样,实现上下翻页. 怎么办呢? 首先要确 ...