Qt QAbstractItemView为截断的项显示ToolTip

在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( 00);
        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 *  20, -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
  • 1
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值