Qt的聊天气泡
作者:互联网
采用了QListWidget作为聊天记录窗口,而每一子项都为QWidget,可以在QWidget绘制自己添加的内容,比如消息内容、头像、名字等,主要可以显示动态GIF表情。
效果图:
mainwindow.h
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QMainWindow>
#include <QDateTime>
namespace Ui {
class MainWindow;
}
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
explicit MainWindow(QWidget *parent = 0);
~MainWindow();
private slots:
void on_pushButton_clicked();
void on_pushButton_2_clicked();
private:
Ui::MainWindow *ui;
int width;
int higth;
QDateTime *time;
};
#endif // MAINWINDOW_H
mainwindow.cpp
#include "mainwindow.h"
#include "ui_mainwindow.h"
#include "chatcontentcircular.h"
#include <QDebug>
#include <QLabel>
#include <QMovie>
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);
width = 0;
higth = 0;
time = new QDateTime();
}
MainWindow::~MainWindow()
{
delete ui;
}
void MainWindow::on_pushButton_clicked()
{
QListWidgetItem *item = new QListWidgetItem;
ChatContentCirCular *chatwid = new ChatContentCirCular();
QString text = ui->lineEdit->text();
chatwid->setuserChatContent(" ");
chatwid->setuserIconName(":/0.bmp");
QLabel *pic = new QLabel(chatwid);
pic->move(80,30);
QMovie *movie = new QMovie(":/3.gif");
pic->setScaledContents(true);
pic->setMovie(movie);
movie->start();
chatwid->settalkTime(time->currentDateTime());
qDebug()<<time->currentDateTime();
chatwid->run(SHOW_TYPE_LEFT);
chatwid->setFixedSize(ui->textEdit->width(),80);
//chatwid->move(width,higth);
//higth += 50;
ui->textEdit->addItem(item);
ui->textEdit->setItemWidget(item,chatwid);
chatwid->show();
QListWidgetItem *_item = new QListWidgetItem;
ChatContentCirCular *_chatwid = new ChatContentCirCular();
_chatwid->setFixedSize(ui->textEdit->width(),40);
ui->textEdit->addItem(_item);
ui->textEdit->setItemWidget(_item,_chatwid);
_chatwid->show();
}
void MainWindow::on_pushButton_2_clicked()
{
QListWidgetItem *item = new QListWidgetItem;
ChatContentCirCular *chatwid = new ChatContentCirCular();
QString text = ui->lineEdit->text();
chatwid->setuserChatContent(text);
chatwid->setuserIconName(":/0.bmp");
chatwid->settalkTime(chatwid->gettalkTime());
qDebug()<<time->currentDateTime();
chatwid->run(SHOW_TYPE_TIME);
chatwid->setFixedSize(ui->textEdit->width(),80);
ui->textEdit->addItem(item);
ui->textEdit->setItemWidget(item,chatwid);
chatwid->show();
}
ChatContentCirCular.h
#include "userchatcontentinterface.h"
#include <QWidget>
#include <QPaintEvent>
#include <QColor>
#include <QString>
#include <QDateTime>
class ChatContentCirCular:public UserChatContentInterface
{
Q_OBJECT
public:
explicit ChatContentCirCular(QWidget *parent = 0);
~ChatContentCirCular();
QString getname();//插件类型名称
qint32 getverison();//插件版本号
qint32 getwindowHeight();
QString getuserIconName();//返回登录用户的图像名称
QString getuserChatContent();//返回登录用户聊天内容
QDateTime gettalkTime();//返回聊天时间
void setuserIconName(QString namestr);//设置登录用户的图像名称
void setuserChatContent(QString usertext);//设置登录用户聊天内容
void settalkTime(QDateTime talktime);//设置聊天时间
void run(show_type_enum type);//开始运行,需要绘制,即开始绘制
protected:
void paintEvent(QPaintEvent *event); //重写QWidget的重绘时间
void calc_text_size(); //计算文字的实际高度
signals:
public slots:
private:
QString plug_name; //插件名称
qint32 plug_version;//插件版本号
QString user_icon_name;//用户图像地址
QString user_chat_content;//用户聊天内容
QDateTime talk_time;//用户聊天时间
show_type_enum show_type; //显示类型
qint32 window_height;//实际的窗口高度
qint32 text_max_width; //文字的最大宽度
qint32 text_min_width;//文字的最小宽度
qint32 text_height;//文字的实际高度
qint32 begin_width_spacing;//起始点距边框的宽度
qint32 begin_height_spacing;//起始点距边框的高度
qint32 icon_width;//图像宽度
qint32 icon_height;//图像高度
qint32 text_height_spacing;//文字距矩形气泡边框的高度
qint32 triangle_width;//横向三角形的宽度
qint32 triangle_height;//横向三角形的高度
qint32 radius; //圆角的半径
QColor framework_border_color;//气泡样式的边框颜色
QColor framework_background_color;//气泡样式的背景颜色
QColor text_color;//文字颜色
QColor time_color;//时间颜色
};
ChatContentCirCular.cpp
#include "chatcontentcircular.h"
#include <QPainter>
#include <QRect>
#include <QPen>
#include <QTextOption>
#include <QFont>
#include <QColor>
#include <QFontMetricsF>
#include <QDebug>
#include <QPainterPath>
ChatContentCirCular::ChatContentCirCular(QWidget *parent):UserChatContentInterface(parent)
{
this->setAttribute(Qt::WA_TranslucentBackground);//设置背景透明
plug_name="circle frame chat content"; //设置插件信息
plug_version=1.0;
show_type=SHOW_TYPE_MIN; //设置变量的初始值
window_height=10;
begin_width_spacing=20;
begin_height_spacing=16;
icon_width=40;
icon_height=40;
text_height_spacing=12;
triangle_width=10;
triangle_height=8;
radius=20;
text_color=QColor(255,255,255);
time_color=QColor(153,153,153);
QFont text_font = this->font();
text_font.setFamily("新宋体");
text_font.setPointSize(10);
this->setFont(text_font);
}
ChatContentCirCular::~ChatContentCirCular()
{
}
QString ChatContentCirCular::getname()
{
return this->plug_name;
}
qint32 ChatContentCirCular::getverison()
{
return this->plug_version;
}
qint32 ChatContentCirCular::getwindowHeight()
{
return this->window_height;
}
QString ChatContentCirCular::getuserIconName()
{
return this->user_icon_name;
}
QString ChatContentCirCular::getuserChatContent()
{
return this->user_chat_content;
}
QDateTime ChatContentCirCular::gettalkTime()
{
return this->talk_time;
}
void ChatContentCirCular::setuserIconName(QString namestr)
{
this->user_icon_name=namestr;
}
void ChatContentCirCular::setuserChatContent(QString usertext)
{
this->user_chat_content=usertext;
this->calc_text_size();
}
void ChatContentCirCular::settalkTime(QDateTime talktime)
{
this->talk_time=talktime;
}
void ChatContentCirCular::run(show_type_enum type)
{
show_type=type;
this->update();
}
void ChatContentCirCular::paintEvent(QPaintEvent *event)
{
QPainter painter(this);
painter.setRenderHints(QPainter::Antialiasing | QPainter::SmoothPixmapTransform);//消锯齿
painter.setFont(this->font());
if(this->show_type==SHOW_TYPE_LEFT)//左边的图像和内容显示
{
//画图像
text_color=QColor(255,255,255);
this->calc_text_size();
QRect icon_rect=QRect(begin_width_spacing,begin_height_spacing,icon_width,icon_height);
painter.setPen(Qt::NoPen);
painter.setBrush(QBrush(Qt::gray));
painter.drawPixmap(icon_rect,QPixmap(user_icon_name));
//画框架
QPainterPath bubble_path;
bubble_path.moveTo(begin_width_spacing+icon_width+triangle_width+radius,begin_height_spacing);
bubble_path.arcTo(begin_width_spacing+icon_width+triangle_width, begin_height_spacing, radius*2, radius*2, 90.0f, 90.0f);
bubble_path.lineTo(begin_width_spacing+icon_width+triangle_width,begin_height_spacing+text_height_spacing+text_height+text_height_spacing-triangle_height);
bubble_path.lineTo(begin_width_spacing+icon_width,begin_height_spacing+text_height_spacing+text_height+text_height_spacing+2);
bubble_path.lineTo(begin_width_spacing+icon_width+triangle_width,begin_height_spacing+text_height_spacing+text_height+text_height_spacing);
bubble_path.lineTo(begin_width_spacing+icon_width+triangle_width+radius+text_max_width,begin_height_spacing+text_height_spacing+text_height+text_height_spacing);
bubble_path.arcTo(begin_width_spacing+icon_width+triangle_width+radius+text_max_width - radius, begin_height_spacing+text_height_spacing+text_height+text_height_spacing - radius*2, radius*2, radius*2, 270.0f, 90.0f);
bubble_path.lineTo(begin_width_spacing+icon_width+triangle_width+radius+text_max_width+radius,begin_height_spacing+radius);
bubble_path.arcTo(begin_width_spacing+icon_width+triangle_width+radius+text_max_width - radius, begin_height_spacing, radius*2, radius*2, 0.0f, 90.0f);
bubble_path.lineTo(begin_width_spacing+icon_width+triangle_width+radius,begin_height_spacing);
QPen pen(QColor(255,255,255));
pen.setWidth(2);
painter.setPen(pen);
painter.setBrush(QBrush(QColor(0,0,0)));
painter.drawPath(bubble_path);
painter.setPen(QColor(255,255,255));
painter.setBrush(QBrush(QColor(255,255,255)));
painter.drawChord(QRectF(begin_width_spacing+icon_width+triangle_width+radius/4,begin_height_spacing+radius/4,radius*2*3/4,radius*2*3/4), 140*16, 30*16);
painter.drawChord(QRectF(begin_width_spacing+icon_width+triangle_width+radius/4,begin_height_spacing+radius/4,radius*2*3/4,radius*2*3/4), 100*16, 20*16);
painter.drawChord(QRectF(begin_width_spacing+icon_width+triangle_width+radius+text_max_width-radius*3/4,begin_height_spacing+radius/4,radius*2*3/4,radius*2*3/4), 0*16, 30*16);
painter.drawChord(QRectF(begin_width_spacing+icon_width+triangle_width+radius+text_max_width-radius*3/4,begin_height_spacing+radius/4,radius*2*3/4,radius*2*3/4), 50*16, 30*16);
painter.drawChord(QRectF(begin_width_spacing+icon_width+triangle_width+radius+text_max_width-radius*3/4,begin_height_spacing+text_height_spacing+text_height+text_height_spacing-radius*7/4,radius*2*3/4,radius*2*3/4), 270*16, 30*16);
painter.drawChord(QRectF(begin_width_spacing+icon_width+triangle_width+radius+text_max_width-radius*3/4,begin_height_spacing+text_height_spacing+text_height+text_height_spacing-radius*7/4,radius*2*3/4,radius*2*3/4), 320*16, 20*16);
//画文字
QPen penText;
penText.setColor(text_color);
painter.setPen(penText);
QTextOption option(Qt::AlignLeft | Qt::AlignVCenter);
option.setWrapMode(QTextOption::WrapAtWordBoundaryOrAnywhere);
painter.drawText(QRect(begin_width_spacing+icon_width+triangle_width+radius,begin_height_spacing+text_height_spacing,text_max_width,text_height),user_chat_content,option);
}
else if(this->show_type==SHOW_TYPE_RIGHT)//右边的图像和内容显示
{
//画图像
text_color=QColor(202,202,202);
int window_current_width=this->width();
this->calc_text_size();
QRect icon_rect=QRect(window_current_width-begin_width_spacing-icon_width,begin_height_spacing,icon_width,icon_height);
painter.setPen(Qt::NoPen);
painter.setBrush(QBrush(Qt::gray));
painter.drawPixmap(icon_rect,QPixmap(user_icon_name));
//画框架
QPainterPath bubble_path;
bubble_path.moveTo(window_current_width-(begin_width_spacing+icon_width+triangle_width+radius),begin_height_spacing);
bubble_path.arcTo(window_current_width-(begin_width_spacing+icon_width+triangle_width+radius+radius), begin_height_spacing, radius*2, radius*2, 90.0f, -90.0f);
bubble_path.lineTo(window_current_width-(begin_width_spacing+icon_width+triangle_width),begin_height_spacing+text_height_spacing+text_height+text_height_spacing-triangle_height);
bubble_path.lineTo(window_current_width-(begin_width_spacing+icon_width),begin_height_spacing+text_height_spacing+text_height+text_height_spacing+2);
bubble_path.lineTo(window_current_width-(begin_width_spacing+icon_width+triangle_width),begin_height_spacing+text_height_spacing+text_height+text_height_spacing);
bubble_path.lineTo(window_current_width-(begin_width_spacing+icon_width+triangle_width+radius+text_max_width),begin_height_spacing+text_height_spacing+text_height+text_height_spacing);
bubble_path.arcTo(window_current_width-(begin_width_spacing+icon_width+triangle_width+radius+text_max_width+radius), begin_height_spacing+text_height_spacing+text_height+text_height_spacing - radius*2, radius*2, radius*2, 270.0f, -90.0f);
bubble_path.lineTo(window_current_width-(begin_width_spacing+icon_width+triangle_width+radius+text_max_width+radius),begin_height_spacing+radius);
bubble_path.arcTo(window_current_width-(begin_width_spacing+icon_width+triangle_width+radius+text_max_width+radius), begin_height_spacing, radius*2, radius*2,180.0f, -90.0f);
bubble_path.lineTo(window_current_width-(begin_width_spacing+icon_width+triangle_width+radius),begin_height_spacing);
QPen pen(QColor(255,255,255));
pen.setWidth(2);
painter.setPen(pen);
painter.setBrush(QBrush(QColor(0,0,0)));
painter.drawPath(bubble_path);
painter.setPen(QColor(255,255,255));
painter.drawChord(QRectF(window_current_width-(begin_width_spacing+icon_width+triangle_width+radius*7/4),begin_height_spacing+radius/4,radius*2*3/4,radius*2*3/4), 90*16, -30*16);
painter.drawChord(QRectF(window_current_width-(begin_width_spacing+icon_width+triangle_width+radius*7/4),begin_height_spacing+radius/4,radius*2*3/4,radius*2*3/4), 40*16, -20*16);
painter.drawChord(QRectF(window_current_width-(begin_width_spacing+icon_width+triangle_width+radius+text_max_width+radius*3/4),begin_height_spacing+text_height_spacing+text_height+text_height_spacing-radius*7/4,radius*2*3/4,radius*2*3/4), 270*16, -30*16);
painter.drawChord(QRectF(window_current_width-(begin_width_spacing+icon_width+triangle_width+radius+text_max_width+radius*3/4),begin_height_spacing+text_height_spacing+text_height+text_height_spacing-radius*7/4,radius*2*3/4,radius*2*3/4), 220*16, -30*16);
painter.drawChord(QRectF(window_current_width-(begin_width_spacing+icon_width+triangle_width+radius+text_max_width+radius*3/4),begin_height_spacing+radius/4,radius*2*3/4,radius*2*3/4), 180*16, -30*16);
painter.drawChord(QRectF(window_current_width-(begin_width_spacing+icon_width+triangle_width+radius+text_max_width+radius*3/4),begin_height_spacing+radius/4,radius*2*3/4,radius*2*3/4), 120*16, -20*16);
//画文字
QPen penText;
penText.setColor(text_color);
painter.setPen(penText);
QTextOption option(Qt::AlignLeft | Qt::AlignVCenter);
option.setWrapMode(QTextOption::WrapAtWordBoundaryOrAnywhere);
painter.drawText(QRect(window_current_width-(begin_width_spacing+icon_width+triangle_width+radius+text_max_width),begin_height_spacing+text_height_spacing,text_max_width,text_height), user_chat_content,option);
}
else if(this->show_type==SHOW_TYPE_TIME)//时间显示
{
QPen time_pen;
time_pen.setColor(time_color);
painter.setPen(time_pen);
QTextOption time_option(Qt::AlignCenter);
time_option.setWrapMode(QTextOption::WrapAtWordBoundaryOrAnywhere);
QFont time_font = painter.font();
time_font.setFamily("MicrosoftYaHei");
time_font.setPointSize(9);
painter.setFont(time_font);
painter.drawText(this->rect(),talk_time.toString("yyyy-MM-dd HH:mm:ss"),time_option);
}
}
void ChatContentCirCular::calc_text_size()
{
QFontMetrics metrics = QFontMetrics(this->font());
text_min_width=metrics.width("A")*2;
qint32 min_width=begin_width_spacing+icon_width+triangle_width+radius+icon_width+begin_width_spacing;
if(this->width()<min_width+text_min_width)//最小显示即一行只显示一个汉字
{
this->setMinimumWidth(min_width+text_min_width);
}
text_max_width=this->width()-min_width;//框架的最大文字宽度
qint32 real_width=metrics.width(this->user_chat_content);
if(real_width<text_max_width)
{
text_max_width=real_width;
text_height=text_height_spacing+metrics.height()+text_height_spacing>radius*2? metrics.height(): radius*2-text_height_spacing-text_height_spacing ;
}
else
{
QRect textRect=QRect(0,0,text_max_width,0);
int flags = Qt::TextWordWrap; // 自动换行
textRect=metrics.boundingRect(textRect, flags, user_chat_content);
text_height=text_height_spacing+textRect.height()+text_height_spacing>radius*2? textRect.height(): radius*2-text_height_spacing-text_height_spacing ;
}
window_height=text_height_spacing+text_height+text_height_spacing>icon_height? text_height_spacing+text_height+text_height_spacing: icon_height;
window_height=begin_height_spacing+window_height+begin_height_spacing;
}
UserChatContentInterface.h`
#include <QWidget>
#include <QString>
#include <QDateTime>
#include <QSize>
typedef enum {
SHOW_TYPE_MIN=1,
SHOW_TYPE_LEFT,//窗口从左到右显示
SHOW_TYPE_RIGHT,//窗口从右到左显示
SHOW_TYPE_TIME //时间显示
}show_type_enum;
class UserChatContentInterface:public QWidget
{
public:
UserChatContentInterface(QWidget *parent = 0):QWidget(parent){}
virtual QString getname()=0;//插件类型名称
virtual qint32 getverison()=0;//插件版本号
virtual qint32 getwindowHeight()=0;//返回窗口的实际合适高度
virtual QString getuserIconName()=0;//返回用户的图像名称
virtual QString getuserChatContent()=0;//返回用户聊天内容
virtual QDateTime gettalkTime()=0;//返回聊天时间
virtual void setuserIconName(QString namestr)=0;//设置用户的图像名称
virtual void setuserChatContent(QString usertext)=0;//设置用户聊天内容
virtual void settalkTime(QDateTime talktime)=0;//设置聊天时间
virtual void run(show_type_enum type)=0;//开始运行,需要绘制,即开始绘制
};
标签:begin,Qt,text,spacing,height,width,radius,聊天,气泡 来源: https://blog.csdn.net/qq_46495964/article/details/113823706