Qt5气泡式聊天框——QListWidget+QPainter实现
文章目录
- 1、简介
- 2、效果图
- 3、实现原理
- 4、核心代码
- 4.1、头文件
- 4.2、源文件
- 5、代码分享
- 5.1、Github
- 5.2、码云
1、简介
由于最近的项目需要,做了些相关IM的工作。所以聊天框也是必不可少的一部分。聊天框的制作分很多种,本文以QListWidget+QPainter绘制的Item做了一个Demo。该Demo只是做一个示例,代码已公布如下,需要的拿去!
2、效果图
3、实现原理
气泡式聊天的显示是由QListWidget作为控件,每个气泡是由QListWidgetItem提升成QWidget来实现的。每个气泡可以理解位是一个QWidget,这样可以自由布置QWidget里面的内容。每个Item保存聊天的对话、发送状态、时间、种类等。
这个QWidget主要是显示一个头像+气泡,气泡里面是聊天的内容等。
气泡是在paintEvent事件中,采用QPainter来绘制的。
4、核心代码
4.1、头文件
#ifndef QNCHATMESSAGE_H
#define QNCHATMESSAGE_H#include <QWidget>class QPaintEvent;
class QPainter;
class QLabel;
class QMovie;class QNChatMessage : public QWidget
{Q_OBJECT
public:explicit QNChatMessage(QWidget *parent = nullptr);enum User_Type{User_System,//系统User_Me, //自己User_She, //用户User_Time, //时间};void setTextSuccess();void setText(QString text, QString time, QSize allSize, User_Type userType);QSize getRealString(QString src);QSize fontRect(QString str);inline QString text() {return m_msg;}inline QString time() {return m_time;}inline User_Type userType() {return m_userType;}
protected:void paintEvent(QPaintEvent *event);
private:QString m_msg;QString m_time;QString m_curTime;QSize m_allSize;User_Type m_userType = User_System;int m_kuangWidth;int m_textWidth;int m_spaceWid;int m_lineHeight;QRect m_iconLeftRect;QRect m_iconRightRect;QRect m_sanjiaoLeftRect;QRect m_sanjiaoRightRect;QRect m_kuangLeftRect;QRect m_kuangRightRect;QRect m_textLeftRect;QRect m_textRightRect;QPixmap m_leftPixmap;QPixmap m_rightPixmap;QLabel* m_loading = Q_NULLPTR;QMovie* m_loadingMovie = Q_NULLPTR;bool m_isSending = false;
};#endif // QNCHATMESSAGE_H
4.2、源文件
#include "qnchatmessage.h"
#include <QFontMetrics>
#include <QPaintEvent>
#include <QDateTime>
#include <QPainter>
#include <QMovie>
#include <QLabel>
#include <QDebug>QNChatMessage::QNChatMessage(QWidget *parent) : QWidget(parent)
{QFont te_font = this->font();te_font.setFamily("MicrosoftYaHei");te_font.setPointSize(12);
// te_font.setWordSpacing(0);
// te_font.setLetterSpacing(QFont::PercentageSpacing,0);
// te_font.setLetterSpacing(QFont::PercentageSpacing, 100); //300%,100为默认 //设置字间距%
// te_font.setLetterSpacing(QFont::AbsoluteSpacing, 0); //设置字间距为3像素 //设置字间距像素值this->setFont(te_font);m_leftPixmap = QPixmap(":/img/Customer Copy.png");m_rightPixmap = QPixmap(":/img/CustomerService.png");m_loadingMovie = new QMovie(this);m_loadingMovie->setFileName(":/img/loading4.gif");m_loading = new QLabel(this);m_loading->setMovie(m_loadingMovie);m_loading->resize(16,16);m_loading->setAttribute(Qt::WA_TranslucentBackground , true);m_loading->setAutoFillBackground(false);
}void QNChatMessage::setTextSuccess()
{m_loading->hide();m_loadingMovie->stop();m_isSending = true;
}void QNChatMessage::setText(QString text, QString time, QSize allSize, QNChatMessage::User_Type userType)
{m_msg = text;m_userType = userType;m_time = time;m_curTime = QDateTime::fromTime_t(time.toInt()).toString("hh:mm");m_allSize = allSize;if(userType == User_Me) {if(!m_isSending) {m_loading->move(m_kuangRightRect.x() - m_loading->width() - 10, m_kuangRightRect.y()+m_kuangRightRect.height()/2- m_loading->height()/2);m_loading->show();m_loadingMovie->start();}} else {m_loading->hide();}this->update();
}QSize QNChatMessage::fontRect(QString str)
{m_msg = str;int minHei = 30;int iconWH = 40;int iconSpaceW = 20;int iconRectW = 5;int iconTMPH = 10;int sanJiaoW = 6;int kuangTMP = 20;int textSpaceRect = 12;m_kuangWidth = this->width() - kuangTMP - 2*(iconWH+iconSpaceW+iconRectW);m_textWidth = m_kuangWidth - 2*textSpaceRect;m_spaceWid = this->width() - m_textWidth;m_iconLeftRect = QRect(iconSpaceW, iconTMPH, iconWH, iconWH);m_iconRightRect = QRect(this->width() - iconSpaceW - iconWH, iconTMPH, iconWH, iconWH);QSize size = getRealString(m_msg); // 整个的sizeqDebug() << "fontRect Size:" << size;int hei = size.height() < minHei ? minHei : size.height();m_sanjiaoLeftRect = QRect(iconWH+iconSpaceW+iconRectW, m_lineHeight/2, sanJiaoW, hei - m_lineHeight);m_sanjiaoRightRect = QRect(this->width() - iconRectW - iconWH - iconSpaceW - sanJiaoW, m_lineHeight/2, sanJiaoW, hei - m_lineHeight);if(size.width() < (m_textWidth+m_spaceWid)) {m_kuangLeftRect.setRect(m_sanjiaoLeftRect.x()+m_sanjiaoLeftRect.width(), m_lineHeight/4*3, size.width()-m_spaceWid+2*textSpaceRect, hei-m_lineHeight);m_kuangRightRect.setRect(this->width() - size.width() + m_spaceWid - 2*textSpaceRect - iconWH - iconSpaceW - iconRectW - sanJiaoW,m_lineHeight/4*3, size.width()-m_spaceWid+2*textSpaceRect, hei-m_lineHeight);} else {m_kuangLeftRect.setRect(m_sanjiaoLeftRect.x()+m_sanjiaoLeftRect.width(), m_lineHeight/4*3, m_kuangWidth, hei-m_lineHeight);m_kuangRightRect.setRect(iconWH + kuangTMP + iconSpaceW + iconRectW - sanJiaoW, m_lineHeight/4*3, m_kuangWidth, hei-m_lineHeight);}m_textLeftRect.setRect(m_kuangLeftRect.x()+textSpaceRect,m_kuangLeftRect.y()+iconTMPH,m_kuangLeftRect.width()-2*textSpaceRect,m_kuangLeftRect.height()-2*iconTMPH);m_textRightRect.setRect(m_kuangRightRect.x()+textSpaceRect,m_kuangRightRect.y()+iconTMPH,m_kuangRightRect.width()-2*textSpaceRect,m_kuangRightRect.height()-2*iconTMPH);return QSize(size.width(), hei);
}QSize QNChatMessage::getRealString(QString src)
{QFontMetricsF fm(this->font());m_lineHeight = fm.lineSpacing();int nCount = src.count("\n");int nMaxWidth = 0;if(nCount == 0) {nMaxWidth = fm.width(src);QString value = src;if(nMaxWidth > m_textWidth) {nMaxWidth = m_textWidth;int size = m_textWidth / fm.width(" ");int num = fm.width(value) / m_textWidth;int ttmp = num*fm.width(" ");num = ( fm.width(value) ) / m_textWidth;nCount += num;QString temp = "";for(int i = 0; i < num; i++) {temp += value.mid(i*size, (i+1)*size) + "\n";}src.replace(value, temp);}} else {for(int i = 0; i < (nCount + 1); i++) {QString value = src.split("\n").at(i);nMaxWidth = fm.width(value) > nMaxWidth ? fm.width(value) : nMaxWidth;if(fm.width(value) > m_textWidth) {nMaxWidth = m_textWidth;int size = m_textWidth / fm.width(" ");int num = fm.width(value) / m_textWidth;num = ((i+num)*fm.width(" ") + fm.width(value)) / m_textWidth;nCount += num;QString temp = "";for(int i = 0; i < num; i++) {temp += value.mid(i*size, (i+1)*size) + "\n";}src.replace(value, temp);}}}return QSize(nMaxWidth+m_spaceWid, (nCount + 1) * m_lineHeight+2*m_lineHeight);
}void QNChatMessage::paintEvent(QPaintEvent *event)
{Q_UNUSED(event);QPainter painter(this);painter.setRenderHints(QPainter::Antialiasing | QPainter::SmoothPixmapTransform);//消锯齿painter.setPen(Qt::NoPen);painter.setBrush(QBrush(Qt::gray));if(m_userType == User_Type::User_She) { // 用户//头像
// painter.drawRoundedRect(m_iconLeftRect,m_iconLeftRect.width(),m_iconLeftRect.height());painter.drawPixmap(m_iconLeftRect, m_leftPixmap);//框加边QColor col_KuangB(234, 234, 234);painter.setBrush(QBrush(col_KuangB));painter.drawRoundedRect(m_kuangLeftRect.x()-1,m_kuangLeftRect.y()-1,m_kuangLeftRect.width()+2,m_kuangLeftRect.height()+2,4,4);//框QColor col_Kuang(255,255,255);painter.setBrush(QBrush(col_Kuang));painter.drawRoundedRect(m_kuangLeftRect,4,4);//三角QPointF points[3] = {QPointF(m_sanjiaoLeftRect.x(), 30),QPointF(m_sanjiaoLeftRect.x()+m_sanjiaoLeftRect.width(), 25),QPointF(m_sanjiaoLeftRect.x()+m_sanjiaoLeftRect.width(), 35),};QPen pen;pen.setColor(col_Kuang);painter.setPen(pen);painter.drawPolygon(points, 3);//三角加边QPen penSanJiaoBian;penSanJiaoBian.setColor(col_KuangB);painter.setPen(penSanJiaoBian);painter.drawLine(QPointF(m_sanjiaoLeftRect.x() - 1, 30), QPointF(m_sanjiaoLeftRect.x()+m_sanjiaoLeftRect.width(), 24));painter.drawLine(QPointF(m_sanjiaoLeftRect.x() - 1, 30), QPointF(m_sanjiaoLeftRect.x()+m_sanjiaoLeftRect.width(), 36));//内容QPen penText;penText.setColor(QColor(51,51,51));painter.setPen(penText);QTextOption option(Qt::AlignLeft | Qt::AlignVCenter);option.setWrapMode(QTextOption::WrapAtWordBoundaryOrAnywhere);painter.setFont(this->font());painter.drawText(m_textLeftRect, m_msg,option);} else if(m_userType == User_Type::User_Me) { // 自己//头像
// painter.drawRoundedRect(m_iconRightRect,m_iconRightRect.width(),m_iconRightRect.height());painter.drawPixmap(m_iconRightRect, m_rightPixmap);//框QColor col_Kuang(75,164,242);painter.setBrush(QBrush(col_Kuang));painter.drawRoundedRect(m_kuangRightRect,4,4);//三角QPointF points[3] = {QPointF(m_sanjiaoRightRect.x()+m_sanjiaoRightRect.width(), 30),QPointF(m_sanjiaoRightRect.x(), 25),QPointF(m_sanjiaoRightRect.x(), 35),};QPen pen;pen.setColor(col_Kuang);painter.setPen(pen);painter.drawPolygon(points, 3);//内容QPen penText;penText.setColor(Qt::white);painter.setPen(penText);QTextOption option(Qt::AlignLeft | Qt::AlignVCenter);option.setWrapMode(QTextOption::WrapAtWordBoundaryOrAnywhere);painter.setFont(this->font());painter.drawText(m_textRightRect,m_msg,option);} else if(m_userType == User_Type::User_Time) { // 时间QPen penText;penText.setColor(QColor(153,153,153));painter.setPen(penText);QTextOption option(Qt::AlignCenter);option.setWrapMode(QTextOption::WrapAtWordBoundaryOrAnywhere);QFont te_font = this->font();te_font.setFamily("MicrosoftYaHei");te_font.setPointSize(10);painter.setFont(te_font);painter.drawText(this->rect(),m_curTime,option);}
}
5、代码分享
5.1、Github
地址:https://github.com/ShaShiDiZhuanLan/Demo_MessageChat_Qt
5.2、码云
地址:https://gitee.com/ShaShiDiZhuanLan/Demo_MessageChat
Qt5气泡式聊天框——QListWidget+QPainter实现相关推荐
- Qt5气泡式聊天框,QT聊天软件
一直想做一款聊天软件.最近终于有了时间和机会.源代码已经开放.欢迎关注和贡献代码啊.嘿嘿 https://github.com/qcdong2016/Octopus
- qq聊天框java_jQuery实现简单QQ聊天框
本文实例为大家分享了jQuery实现简单QQ聊天框的具体代码,供大家参考,具体内容如下 先放一张效果图! 1.首先我们把基本框架搭出来,还要准备三张图片用来当作头像,下面是html的内容 关闭(C) ...
- 基于socket的线上聊天框
聊天框1.0 使用说明: 要求Linux环境,虚拟机或者WSL均可 命令行执行 g++ Server.cpp -o Server 和 g++ Client.cpp -o Client 进行编译 线程A ...
- 山寨一把QQ移动终端聊天框,网页版效果其实也很好的!
手机QQ的聊天框很漂亮,包括好多短信交互框也做成类似的风格,各种效果,各种炫,至于不规则形状的那种(称为手绘风格),比较麻烦,这里使用CSS3新特性,border-radius,进行信息框交互内容的设 ...
- 纯CSS实现气泡聊天框的方法
<!DOCTYPE html> <html> <head> <meta http-equiv="Content-Type" content ...
- php类似微信聊天框,仿微信聊天功能
摘要: 微信聊天 window.onload = () => { // 获取按钮 let btn = document.getElementById('btn'); // 获取输入框 let t ...
- Andriod 实现一个微信聊天框(一)
Andriod 实现一个微信聊天框(一) 这周做了第一次Andriod作业,虽然是对着老师的视频桥的代码,还是遇到了相当多的技术问题和bug,再次记录一下解决问题的过程,以便于后期复习使用. 这次实验 ...
- 我的世界服务器无法发送聊天信息,我的世界聊天框指令传送 | 手游网游页游攻略大全...
发布时间:2017-04-26 我的世界聊天框有什么用?相信大部分玩家在玩游戏的时候聊天框只是一个聊天用的工具,可是你想过这些聊天框也能玩出花样吗?今天游戏园小编就为大家带来了我的世界跳舞的聊天框,来 ...
- php做到聊天发图片,网页聊天框发送表情图片实现方法
话不多说,单刀直入正题. NO 1:标签定义方法 这种方法和平常使用的输入框没什么区别,一个textarea解决问题,原理是输入特定格式的文字符号,显示的时候通过定义的规则解析,显示表情,至于图片则是 ...
最新文章
- 晶科能源坐稳全球光伏组件制造商“头把交椅”
- Windows Tftpd32 DHCP服务器 使用
- Manjaro使用笔记-使用中国源的方法
- Visual Studio 2010快捷键大全
- AMD Cubemapgen for physically based rendering
- MongoDB 学习-MongoDB 的基本操作(二)
- android log 码率,webrtc之Android视频质量提升:保帧率降码率
- ant里面table嵌套子表格_ElementUI el-table行内编辑验证,动态增减行
- 算法真的“难”吗?其实也不见得...
- 区块链学习之《区块链技术指南》读书笔记
- android wifi信号检测工具,推荐4个专业又实用的WiFi检测工具,了解一下
- echarts地图各种点位实现
- 关于oracle端口映射的远程连接
- mongodb一致性协议_Mongodb选举机制
- js:为窗口盒子添加拖拽事件
- opencv去除图片水印
- 根据经纬度计算指定范围内或者附近的人(java)
- 声纹识别概述(1)初识
- SQL语句一二三之SQL基本语句
- MFC TabControl插件 子对话框调用主对话框功能函数和变量