表情选择控件在聊天应用中经常要用到,做起来虽然不复杂但是很繁琐,特别是有些图标需要按顺序排列。每次重做必然是很费时,所以我将聊天表情选择控件封装成一个独立的类QFaceSelectWidget,方便直接应用到自己的项目中。
先来看看效果图:
测试程序是一个对话框,里面放有一个QPushButton和一个QLabel,水平布局。点击按钮弹出“表情选择框",选择表情后"表情选择框"关闭,QLabel中显示刚才选择的表情。"表情选择框"中的表情都是gif图片,排列顺序和QQ一样。
如何应用到自己的项目中?
下面是QFaceSelectWidget项目的文件结构,其中gui目录下存放了两个类文件QFaceSelectWidget和QGifLabel,前者是”表情选择框“,后者用来显示Gif动画。res.qrc下面是用到的表情资源,main.cpp 是测试代码。
步骤1:将C++文件拷贝到你的项目中
qfaceselectwidget.cpp
qfaceselectwidget.h
qgiflabel.cpp
qgiflabel.h
步骤2:将表情资源添加到你的资源文件中
步骤3:使用
在需要用到”表情选择框“的源文件中,添加头文件"qfaceselectwidget.h",然后创建QFaceSelectWidget实例对象,设置相应的信号/槽处理。
// 第一个参数指定聊天表情所在的目录(本地文件系统路径 或 Qt资源文件路径) QFaceSelectWidget faceSelectWidget(":/faces/res/images/faces"); // 按钮点击时显示”聊天表情框“ // showOnTop()的第一个参数:”聊天表情框“显示在该参数所指定位置的上方(屏幕坐标系)。 // showOnTop()的第二个参数:”聊天表情框“在参数一所指定的位置”向上“偏移参数二所指定的距离。 QObject::connect(btn, &QPushButton::clicked, [=, &faceSelectWidget]{ faceSelectWidget.showOnTop(QCursor::pos(), btn->height()/2); }); // 表情选择完成后,在label中播放所选择的gif动画 QObject::connect(&faceSelectWidget, &QFaceSelectWidget::selected, [=](const QString &filename){ gifLabel->setFileName(filename); gifLabel->start(); });
实现过程简介
QFaceSelectWidget 使用表格布局,每个单元格是一个QGifLabel用来播放gif动画,设置WindowFlags(Qt::Popup)这样窗口没有标题栏。
QLabel可以通过设置QMovie来显示Gif动画,但是也有一些不方便的地方,所以我从QLabel类派生了QGifLabel,方便处理鼠标点击、移入和移出事件,同时对Gif动画的控制也更为方便直观,下面是QGifLabel的申明:
class QGifLabel : public QLabel { Q_OBJECT public: explicit QGifLabel(QWidget *parent = 0); QGifLabel(const QString &fileName, QWidget *parent = 0); void setFileName(const QString &fileName, bool start = false); void start(); void stop(); signals: void clicked(const QString &fileName); protected: void mouseReleaseEvent(QMouseEvent *e); void enterEvent(QEvent *e); void leaveEvent(QEvent *e); private: QMovie *m_movie; };
QFaceSelectWidget 的构造函数需要指定表情资源的目录,在构造函数内部会调用mapIconName()来映射表情资源文件名到m_iconName中,表情从m_iconName所指定的路径加载,这样的好处是你可以在mapIconName()中修改表情的显示顺序。showOnTop()会计算表情选择框显示的合适位置。selected()是一个信号,当选择表情后会执行两个发射该信号,该信号会将所选择的表情的路径传递出去,供外部使用。
class QFaceSelectWidget : public QWidget { Q_OBJECT public: explicit QFaceSelectWidget(const QString &faceIconDir, QWidget *parent = 0); ~QFaceSelectWidget(); void showOnTop(QPoint &pos, int offsetY = 0); signals: void selected(const QString &fileName); private: QMap<int, QString> m_iconName; void mapIconName(); };
更多细节可以查阅源文件,源代码下载地址:http://git.oschina.net/xiaohui_hubei/Code-Home/raw/master/QFaceSelectWidget.7z。