Qt 之 QQ系统表情(五)
来源:互联网 发布:淘宝产品运作方案 编辑:程序博客网 时间:2024/05/13 16:12
简述
在Qt 之 QQ系统表情(四) 中我们通过用nativeEvent事件的方法实现了自定义表情窗口,这一篇将通过继承QLabel的方式来实现。同时我也在研究过程中发现了一些小问题。
代码Go!
代码之路
MyEmotionItemWidget.cpp
MyEmotionItemWidget::MyEmotionItemWidget(QString fileName , QSize emotionMoiveSize) : QLabel(NULL){ //首先构造函数中进行初始化; QMovie* iconMovie = new QMovie; iconMovie->setFileName(fileName); this->setMovie(iconMovie); setContentsMargins(3, 3, 3, 3); iconMovie->setScaledSize(QSize(emotionMoiveSize.width(), emotionMoiveSize.height())); //为了动态图片正常显示,(不加上start图片不显示,不加上stop图片一种处于动态效果) iconMovie->start(); iconMovie->stop(); setStyleSheet("QLabel:hover{border: 1px solid rgb(111, 156, 207);\ background: rgba(255, 255, 255, 200);}");}MyEmotionItemWidget::~MyEmotionItemWidget(){}// 鼠标进入Label事件void MyEmotionItemWidget::enterEvent(QEvent* event){ QMovie* movie = this->movie(); movie->start(); // 当鼠标悬浮在item上时修改margin值达到表情切换效果,见下图(在鼠标从一个表情滑到另一个表情时) setContentsMargins(4, 2, 2, 4); return __super::enterEvent(event);}// 鼠标离开Label事件void MyEmotionItemWidget::leaveEvent(QEvent* event){ QMovie* movie = this->movie(); movie->jumpToFrame(0); movie->stop(); //恢复原来的margin setContentsMargins(3, 3, 3, 3); return __super::leaveEvent(event);}
MyEmotionWidget.cpp
MyEmotionWidget::MyEmotionWidget(QWidget *parent) : QTableWidget(parent) , m_tableRow(0) , m_tableColumn(0) , m_preRow(0) , m_preColumn(0) , m_maxRow(6) , m_emotionSize(QSize(0 , 0)) , m_emotionMovieSize(QSize(0 , 0)){ loadStyleSheet();}MyEmotionWidget::~MyEmotionWidget(){}// 直接从文件中获取样式void MyEmotionWidget::loadStyleSheet(){ QFile file(":/Resources/QSS/myemotion.css"); file.open(QFile::ReadOnly); QString strSheet = file.readAll(); QString styleSheet = this->styleSheet(); styleSheet += strSheet; this->setStyleSheet(styleSheet);}// 设置表情窗口的行列数目void MyEmotionWidget::setRowAndColumn(int row, int column){ m_tableRow = row; m_tableColumn = column;}// 设置item表情框大小void MyEmotionWidget::setEmotionSize(QSize emotionSize){ m_emotionSize = emotionSize;}// 设置表情movie大小void MyEmotionWidget::setEmotionMovieSize(QSize emotionMovieSize){ m_emotionMovieSize = emotionMovieSize;}// 设置最大行数void MyEmotionWidget::setMaxRow(int maxRow){ m_maxRow = maxRow;}// 设置完参数后,进行初始化void MyEmotionWidget::initTableWidget(){ // 设置无焦点 this->setFocusPolicy(Qt::NoFocus); // 设置不可编辑 this->setEditTriggers(QAbstractItemView::NoEditTriggers); // 设置行数 this->setRowCount(m_tableRow); // 设置列数 this->setColumnCount(m_tableColumn); // 设置表头不可见并设置表情item框大小 this->horizontalHeader()->setVisible(false); this->horizontalHeader()->setDefaultSectionSize(m_emotionSize.width()); this->verticalHeader()->setVisible(false); this->verticalHeader()->setDefaultSectionSize(m_emotionSize.height()); // 设置表情窗口的大小,这里行数超过m_maxRow时作了处理,当行数超过给的最大值,则通过滚动 滚动条显示剩余的表情 if (m_tableRow > m_maxRow) { this->setFixedHeight(m_emotionSize.height()*m_maxRow+ 2); // 这里宽度加30,是因为在这种情况下会tablewidget会显示出滚动条,所以为了显示正常,增加一点宽度 this->setFixedWidth(m_emotionSize.width()*m_tableColumn + 30); } else { this->setFixedHeight(m_emotionSize.height()*m_tableRow + 2); this->setFixedWidth(m_emotionSize.width()*m_tableColumn + 2); }}void MyEmotionWidget::addEmotionItem(QString fileName , QString toolTip){ int row = m_emotionList.size() / this->columnCount(); int column = m_emotionList.size() % this->columnCount(); QTableWidgetItem* tableWidgetItem = new QTableWidgetItem; tableWidgetItem->setToolTip(toolTip); this->setItem(row, column, tableWidgetItem); MyEmotionItemWidget* emotionIcon = new MyEmotionItemWidget(fileName , m_emotionMovieSize); this->setCellWidget(row, column, emotionIcon); m_emotionList.push_back(fileName);}
EmotionWindow.cpp
EmotionWindow::EmotionWindow(QWidget *parent) : QWidget(parent) , m_smallEmotionWidget(NULL) , m_normalEmotionWidget(NULL){ ui.setupUi(this); initWindow(); initEmotion();}EmotionWindow::~EmotionWindow(){}void EmotionWindow::initWindow(){ this->setWindowFlags(Qt::FramelessWindowHint); this->setStyleSheet("background:rgb(220, 240, 160);");}// 初始化表情窗口void EmotionWindow::initEmotion(){ // 初始化小表情框 m_smallEmotionWidget = new MyEmotionWidget; m_smallEmotionWidget->setRowAndColumn(4, 4); m_smallEmotionWidget->setEmotionSize(QSize(32, 32)); m_smallEmotionWidget->setEmotionMovieSize(QSize(24, 24)); m_smallEmotionWidget->setMaxRow(4); m_smallEmotionWidget->initTableWidget(); //表情的路径 QString path = ":\\Resources\\QQexpression\\%1.gif"; for (int i = 0; i < 10; i++) { m_smallEmotionWidget->addEmotionItem(path.arg(i + 1), ""); } // 初始化正常表情框; m_normalEmotionWidget = new MyEmotionWidget; m_normalEmotionWidget->setRowAndColumn(10, 14); m_normalEmotionWidget->setEmotionSize(QSize(32, 32)); m_normalEmotionWidget->setEmotionMovieSize(QSize(24, 24)); m_normalEmotionWidget->setMaxRow(6); m_normalEmotionWidget->initTableWidget(); for (int i = 0; i < 132; i++) { m_normalEmotionWidget->addEmotionItem(path.arg(i + 1), ""); } // 初始化样式 m_lableTitle = new QLabel; QVBoxLayout* vLayout = new QVBoxLayout; vLayout->addWidget(m_lableTitle); vLayout->addWidget(m_smallEmotionWidget); vLayout->addWidget(m_normalEmotionWidget); this->setLayout(vLayout);}// 显示小表情窗口void EmotionWindow::showSmallEmotion(QPoint point){ m_normalEmotionWidget->setVisible(false); m_lableTitle->setText("This is Small Emotion Window"); this->setFixedSize(QSize(m_smallEmotionWidget->width() + 20, m_smallEmotionWidget->height() + 50)); move(point); show();}// 显示大表情窗口void EmotionWindow::showNormalEmotion(QPoint point){ m_smallEmotionWidget->setVisible(false); m_lableTitle->setText("This is Normal Emotion Window"); this->setFixedSize(QSize(m_normalEmotionWidget->width() + 20, m_normalEmotionWidget->height() + 50)); move(point); show();}
叙:
相比上一篇使用nativeEvent的方法,通过继承QLabel的方式显得代码更加清爽、简单、方便,相对而言这种方法更胜一筹,同时在使用nativeEvent的方法实现的表情框中出现了两个小小的问题,见下图。
nativeEvent的方法实现
问题一
从图一中可以看出当鼠标悬浮在上下两个表情之间的边框上时,这个时候鼠标的位置实际上是在tableWidget上了,所以此时程序中并没有判断出鼠标移动到另一个表情中,所以下面这个表情一直保持动态显示,与此同时鼠标又不在label上,动态显示的表情就不会显示蓝色的边框。
问题二
仔细看最右边的表情,当鼠标离开这个表情窗口,表情仍然动态显示,检查代码,发现通过nativeEvent捕捉WM_MOUSEMOVE(鼠标移动)事件时,当鼠标移出窗口就不会捕捉,所以当鼠标快速移出窗口之外,同时由于tableWidget最右方与窗口的边距很小,导致未能够及时捕捉到鼠标的移动,所以导致鼠标在窗口之外,表情仍然动态显示。
从这里也可以看出,当鼠标快速移动时,nativeEvent并不会因为鼠标每移动一个像素点就捕捉一次鼠标移动信号,更类似于当鼠标不断移动过程中,nativeEvent会每隔一段时间捕捉鼠标移动(当然这一段时间非常小,基于毫秒级别)。
同时对于mouseMoveEvent事件同样如此,而nativeEvent会先于mouseMoveEvent捕捉到鼠标移动(或者说nativeEvent捕捉到的任何事件都会先于Qt中的事件,具体看Qt助手)。
好了接下来看一看QLabel实现的效果图
验证问题一:
验证问题二:
尾
经过验证,使用继承QLabel方式解决了以上两个“小问题”,如果观察的不够仔细的话这两个小问题不一定会被发现,从另一个角度可以看出我对代码细心研究的态度。不过因当前水平有限,可能代码中也存在一些问题未被发现。So Keep Moving !
进步始于交流,收获源于分享。欢迎大家能够一起交流^_^。
下载
Qt 之实现 QQ系统表情窗口
- Qt 之 QQ系统表情(五)
- Qt 之 QQ系统表情(一)
- Qt 之 QQ系统表情(二)
- Qt 之 QQ系统表情(三)
- Qt 之 QQ系统表情(四)
- Qt 之 QQ系统表情—实现动态显示效果
- qq表情实现之二
- 【Qt】仿QQ表情选择控件
- Android开发之仿QQ表情实现(上)
- Android开发之仿QQ表情实现(下)
- QQ表情
- Qt仿QQ界面,主界面、聊天界面、表情界面
- QQ表情 QQ图片 QQ图像制作方法(一)
- Qt之QQ登录界面(一)
- Qt之QQ登录界面(二)
- Qt之QQ登录界面(三)
- QT分析之WebKit(五)
- QT分析之网络编程(五)
- strip()函数使用
- mysql与JDBC学习笔记
- for循环里面进行数据库查询的处理
- 浅析智能指针二
- wechat4j公众号开发java框架——bug一枚
- Qt 之 QQ系统表情(五)
- iframe父子页面传值
- 【ReactNative】代码学习(一)
- Mountaintop(山峰)
- Android自定义View绘图实现拖影动画
- suricata 3.1 源码分析9
- XZ_iOS之textField占位字距离左侧10,改变占位文字颜色
- WSDL 详解
- JDK 1.8的新特性总结