zoukankan      html  css  js  c++  java
  • QAbstractItemView为截断的项显示ToolTip(在eventFilter函数里覆盖QEvent::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(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

  • 相关阅读:
    贝叶斯思想的实质之我见
    强化学习基础概念理解
    Thinkpad x200用户只能放弃生化危机5(PC版), 希望能全速运行星际争霸2!
    This is it
    今天自己掏腰包去买联通iPhone有几位?
    今天是我的生日:)
    2009已经到来 / 2009 Just the Beginning
    好评如潮的PS3游戏《抵抗2 Resistance2》你玩了吗?
    生化危机5 / BIOHAZARD5 简直就是一款完美的印钞机?(+2009.4.9)
    一部好电影《第九区 District 9》
  • 原文地址:https://www.cnblogs.com/findumars/p/5943787.html
Copyright © 2011-2022 走看看