Qt 之 QQ系统表情(二)

来源:互联网 发布:高招教育软件 编辑:程序博客网 时间:2024/05/21 08:40

简述

继上篇Qt 之 QQ系统表情(一) 中我们实现了简单的表情框,但是还遗留了一个问题,虽然我们能够显示动态的表情,但是总不能让表情框中的每一个表情都动态显示吧(见下图一),这样的效果显然不是我们要的,真正要实现的是当鼠标悬浮在某个表情上才让他动态显示,其他的都显示为静态样式(见图二)。好了,话不多说,代码走起!

图一
图一


图二
图二

代码之路

为了实现这个效果呢,我也是用了很多方法,最后发现了两种方法来达到这个效果。
先看一下QTableWidget的信号:

这里写图片描述

信号到是不少,但是有帮助的信号也就这两信号:

void cellEntered(int row, int column)
This signal is emitted when the mouse cursor enters a cell. The cell is specified by row and column.
This signal is only emitted when mouseTracking is turned on, or when a mouse button is pressed while moving into an item.
简而言之,当鼠标进入tableWidget中某个单元格时会发出。但是只有在mouseTracking 设置为true时,或者在鼠标的一个键被按下的同时鼠标进入tableWidget中某个单元格的。


void itemEntered(QTableWidgetItem * item)
This signal is emitted when the mouse cursor enters an item. The item is the item entered.
This signal is only emitted when mouseTracking is turned on, or when a mouse button is pressed while moving into an item.
单看英文注释发现和cellEntered信号意思差不多,基本算是一字之差,一个是cell一个是item,区别就在这里,仔细看下图中的输出,可以看出在鼠标进入每个单元格的时候都会触发cellEntered信号,而itemEntered信号只有在鼠标进入一个设置了item的单元格中才会触发。

这里写图片描述


测试这两个信号之后发现并没有什么卵用,只有在鼠标慢慢从一个单元格移动到另一个单元格中才会触发,当鼠标快速从一个单元格移动到另一个时这两个信号时有时无,具体可以看下图(图一),所以这两个信号并没有帮助,其实主要是给item设置了cellWidget的原因,如果未设置widget这两个信号是完全可以捕捉到鼠标移动到哪一个单元格(见图二)。
图一
这里写图片描述
图二
这里写图片描述

也有网上说用void entered(const QModelIndex & index)这个信号,效果也如上信号。信号不行,说不定事件就可以呢,继承了QTableWidget类,并重写了mouseMoveEvent事件,结果还是因为给item设置了cellWidget,当鼠标移动到表情图标时根本不会触发mouseMoveEvent事件,既然这个不行就试试eventFilter去专门捕捉mouseMove这个事件,结果当鼠标在图标上移动时根本不会触发mouseMove事件,详情见下图。

bool MyEmotionWidget::eventFilter(QObject *obj, QEvent *event){    //鼠标在图标上移动时输出当前事件    qDebug() << event->type();    return __super::eventFilter(obj, event);}

这里写图片描述

好吧,信号不行,事件也不行,这可咋办。经历重重失败,机智的我最终灵机一动,我干脆不捕捉信号了,我直接通过获取当前鼠标的位置来确定鼠标进入哪一个item,这就靠QTableWidget中的itemAt方法。

QTableWidgetItem * QTableWidget::itemAt(const QPoint & point) const

Returns a pointer to the item at the given point, or returns 0 if point is not covered by an item in the table widget.

代码如下

bool MyEmotionWidget::eventFilter(QObject *obj, QEvent *event){    // 获取当前鼠标的位置    QPoint point = QCursor::pos() - this->pos();    // 根据鼠标的位置获取item    QTableWidgetItem* tableWidgetItem = ui.tableWidget->itemAt(point);    if (tableWidgetItem != NULL)    {        //m_preRow 和 m_preColumn 分别保存了上一次鼠标进入的单元格在QTableWidget中的位置        //如果当前进入的还是同一个则不进行停止动态显示        if(m_preRow != tableWidgetItem->row() || m_preColumn != tableWidgetItem->column())        {            // 将上一次鼠标进入的单元格中的表情停止动态显示            QLabel* preEmotion = (QLabel*)ui.tableWidget->cellWidget(m_preRow, m_preColumn);            if (preEmotion != NULL)            {                QMovie* preMoive = preEmotion->movie();                // 恢复到动态表情图片的第一帧                preMoive->jumpToFrame(0);                preMoive->stop();            }        }        // 将当前鼠标所在的单元格表情开始动态显示,先获取QLabel,再获取QMoive        QLabel* curEmotion = (QLabel*)ui.tableWidget->cellWidget(tableWidgetItem->row(), tableWidgetItem->column());        if (curEmotion != NULL)        {            QMovie* curMoive = curEmotion->movie();            curMoive->start();            m_preRow = tableWidgetItem->row();            m_preColumn = tableWidgetItem->column();        }    }    return __super::eventFilter(obj, event);}

效果图

这里写图片描述

虽然实现了这个效果,但是在eventFilter方法中去根据获取鼠标当前位置获取item并不是十分妥当,下一篇将介绍另外的方法。

3 0
原创粉丝点击