在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. BZOJ 4264 小c找朋友 - hash

    传送门 题目大意: 给定一张无向图,求满足以下条件的点对 (x,y) 数目:对任意点 z (z!=x,y),边 (x,z) 和 (y,z) 同时存在或同时不存在. 题目分析: 首先要分析的出如果xy满 ...

  2. QQ登录, 腾讯开放平台和QQ互联的坑

    原文:QQ登录, 腾讯开放平台和QQ互联的坑 版权声明:本文为博主原创文章,未经博主允许不得转载. https://blog.csdn.net/u012881042/article/details/7 ...

  3. Apparatus, system, and method for automatically minimizing real-time task latency and maximizing non-real time task throughput

    An apparatus, system, and method are provided for automatically minimizing Real-Time (RT) task laten ...

  4. Dojo第一节:学会使用firebug对js,Dojo进行调适

    内容概要: 学会使用firebug的基本功能 1. 简介:Firebug是Firefox的一个插件,用来对js代码进行调适的工具. (官方废话:Firebug是firefox下的一个插件,可以调试全部 ...

  5. 浅析JAVA的垃圾回收机制(GC)

    1.什么是垃圾回收? 垃圾回收(Garbage Collection)是Java虚拟机(JVM)垃圾回收器提供的一种用于在空闲时间不定时回收无任何对象引用的对象占据的内存空间的一种机制. 注意:垃圾回 ...

  6. LockWindowUpdate的函数的用法

    Application.ProcessMessages;LockWindowUpdate(Self.Handle); //锁住当前窗口 LockWindowUpdate(0)//解除锁定窗口 Lock ...

  7. 2 Task中的延续和7种阻塞

    1.wait using System; using System.Threading; using System.Threading.Tasks; namespace 多线程_List { clas ...

  8. lua转换etcd应答

    local function decodeNodes(nodes) local table = {} for _, value in ipairs(nodes) do if value.nodes t ...

  9. C#中的SMTP配置Outlook.Com SMTP主机

    如果你想以编程方式使用    Outlook.com或Gmail帐户作为    SMTP主机    发送电子邮件,也有为了得到这一切工作的几件事情要注意. 使用基本的System.Net.Mail库, ...

  10. 微信公众平台消息接口开发(24)图片识别之人脸识别API

    微信公众平台开发模式 微信 公众平台 消息接口 开发模式 企业微信公众平台 图片识别 人脸识别 API 作者:方倍工作室 原文:http://www.cnblogs.com/txw1958/archi ...