在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(在eventFilter函数里覆盖QEvent::ToolTip事件)的更多相关文章

  1. QAbstractItemView为截断的项显示ToolTip(使用事件过滤)

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

  2. css截断长文本显示

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

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

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

  4. echarts 自定义配置带单位的 tooltip 提示框方法 和 圆环数据 tooltip 过长超出屏幕

    -------tip1-------- 在 tooltip  里边配置:拼接字符串: tooltip : { trigger: 'axis', formatter:function(params) { ...

  5. 解决:npm中 下载速度慢 和(无法将“nrm”项识别为 cmdlet、函数、脚本文件或可运行程序的名称。请检查名称的拼写,如果包括路径,请确保路径正确, 然后再试一次)。

    1.解决下载速度 因为我们npm下载默认是,连接国外的服务器,所以网速不是特别好的时候,可能下不了包 安装nrm 使用 npm i nrm -g 我们的一般工具包都是下载到全局 安装完毕之后,可以运行 ...

  6. VSCode下,项识别为 cmdlet、函数、脚本文件或可运行程序的名称。

    vscode下webpack错误:无法将“webpack”项识别为 cmdlet.函数.脚本文件或可运行程序的名称.请检查名称的拼写,如果包括路径,请确保路径正确,然后再试一次. 解决方法: 1.因为 ...

  7. visual studio code运行时报错,无法将“cnpm”项识别为 cmdlet、函数、脚本文件或可运行程序的名称,Cannot find module 'webpack'

    前言 因公司技术需求,这段时间成功进入了Vue 2.0 的坑,刚用起Visual Studio Code,却发现问题很多,发现一个错误:cnpm : 无法将“cnpm”项识别为 cmdlet.函数.脚 ...

  8. '无法将“vue”项识别为 cmdlet、函数、脚本文件或可运行程序的名称' 或 'vue不是内部或外部命令' 的解决方法

    如果在使用 vue 初始化项目的时候提示: vue : 无法将“vue”项识别为 cmdlet.函数.脚本文件或可运行程序的名称.请检查名称的拼写,如果包括路径,请确保路径正确,然后再试一次. 或者: ...

  9. 无法将“Scaffold-DbContext”项识别为 cmdlet、函数、脚本文件或可运行程序的名称...

    原文链接:https://my.oschina.net/taadis/blog/889560 为什么80%的码农都做不了架构师?>>>     PM> Scaffold-DbC ...

随机推荐

  1. 错误源:WebForms UnobtrusiveValidationMode requires a ScriptResourceMapping for 'jquery'. Please add a ScriptResourceMapping named jquery(case-sensitive).

    Server Error in '/' Application. WebForms UnobtrusiveValidationMode requires a ScriptResourceMapping ...

  2. Spring切面处理

    切面类DictionaryAOP 里面有一个全局变量systemTestDomain <bean id="dictionaryAOP" class="test.Di ...

  3. 转:ASP.NET MVC 3 and App_Code folder

    问题: In ASP.NET Webform, App_Code is standardfolder to putting code and using it at run-time.But I th ...

  4. C# ACM poj1002

    排序 public static void acm1002(string[] azx) { string[] a = new string[azx.Length]; ; i < azx.Leng ...

  5. 03静态链表_StaticLinkList--(线性表)

    #include "string.h" #include "ctype.h" #include "stdio.h" #include &qu ...

  6. Server Error The server encountered an error and could not complete your request. 新建站点模版失败

    500 Server Error Error: Server Error The server encountered an error and could not complete your req ...

  7. CSS高度塌陷

    问题描述:当父元素只包含浮动的元素的时候,且父元素没有设置高度,如果父元素设置了边框border,那么看起来子元素不在父元素之内. 比如这样: html: <div id="paren ...

  8. How to: Signing Installers You Create with Inno Setup

    Original Link: http://revolution.screenstepslive.com/s/revolution/m/10695/l/95041-signing-installers ...

  9. 模板:函数memset

    需要的头文件 <memory.h> or <string.h> memset   函数介绍 void *memset(void *s, int ch, size_t n); 函 ...

  10. OpenJudge 2811 熄灯问题 / Poj 1222 EXTENDED LIGHTS OUT

    1.链接地址: http://bailian.openjudge.cn/practice/2811 http://poj.org/problem?id=1222 2.题目: 总时间限制: 1000ms ...