QPainter 繪製氣泡對話框QWidget

QPainter簡介

QPainter中常用圖像繪製函數
函數 功能 

drawArc()

繪製圓弧

drawChord()

繪製弦

drawConvexPolygon()

繪製凸多邊形

drawEllipse()

繪製橢圓

drawLine()

繪製線條

drawPie()

繪製扇形

drawPoint()

繪製點

drawPolygon()

繪製多邊形

drawPolyline()

繪製折線

drawRect()

繪製矩形

drawRoundedRect()

繪製圓角矩形

抽象接口類

#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;//開始運行,需要繪製,即開始繪製
};

氣泡對話框1


#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;//時間顏色
};
#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;
}

效果:

氣泡對話框2

#ifndef CHATCONTENTNOFRAME_H
#define CHATCONTENTRECT_H

#include "userchatcontentinterface.h"

#include <QWidget>
#include <QPaintEvent>
#include <QColor>
#include <QString>
#include <QDateTime>

class ChatContentNoFrame:public UserChatContentInterface
{
     Q_OBJECT
public:
    explicit ChatContentNoFrame(QWidget *parent = 0);
    ~ChatContentNoFrame();

    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);
    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_width_spacing;//文字距矩形邊框氣泡的邊框的寬度
    qint32 text_height_spacing;//文字距矩形氣泡邊框的高度

    QColor text_color;//文字顏色
    QColor time_color;//時間顏色
};

#endif // CHATCONTENTRECT_H
#include "chatcontentnoframe.h"
#include <QPainter>
#include <QRect>
#include <QPen>
#include <QTextOption>
#include <QFont>
#include <QColor>
#include <QFontMetricsF>
#include <QDebug>

ChatContentNoFrame::ChatContentNoFrame(QWidget *parent):UserChatContentInterface(parent)
{
    this->setAttribute(Qt::WA_TranslucentBackground);//設置背景透明
    plug_name="no 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_width_spacing=12;
    text_height_spacing=12;

    text_color=QColor(0,0,0);
    time_color=QColor(153,153,153);

    QFont text_font = this->font();
    text_font.setFamily("黑體");
    text_font.setPointSize(10);
    this->setFont(text_font);
}

ChatContentNoFrame::~ChatContentNoFrame()
{

}

QString ChatContentNoFrame::getname()
{
    return this->plug_name;
}

qint32 ChatContentNoFrame::getverison()
{
    return this->plug_version;
}

qint32 ChatContentNoFrame::getwindowHeight()
{
    return this->window_height;
}

QString ChatContentNoFrame::getuserIconName()
{
    return this->user_icon_name;
}

QString ChatContentNoFrame::getuserChatContent()
{
    return this->user_chat_content;
}

QDateTime ChatContentNoFrame::gettalkTime()
{
    return this->talk_time;
}

void ChatContentNoFrame::setuserIconName(QString namestr)
{
    this->user_icon_name=namestr;
}

void ChatContentNoFrame::setuserChatContent(QString usertext)
{
    this->user_chat_content=usertext;
    this->calc_text_size();
}

void ChatContentNoFrame::settalkTime(QDateTime talktime)
{
    this->talk_time=talktime;
}

void ChatContentNoFrame::run(show_type_enum type)
{
    show_type=type;
    this->update();
}

void ChatContentNoFrame::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(0,0,64);
        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));

        //畫框架
        QRect textRect=QRect(begin_width_spacing+icon_width+text_width_spacing,begin_height_spacing,text_max_width+text_width_spacing,text_height_spacing+text_height+text_height_spacing);

        //畫文字
        QPen penText;
        penText.setColor(text_color);
        painter.setPen(penText);

        QTextOption option(Qt::AlignLeft | Qt::AlignVCenter);
        option.setWrapMode(QTextOption::WrapAtWordBoundaryOrAnywhere);
        painter.drawText(textRect, user_chat_content,option);
    }
    else if(this->show_type==SHOW_TYPE_RIGHT)//右邊的圖像和內容顯示
    {
        //畫圖像
        text_color=QColor(0,128,128);
        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));

        //畫框架
        QRect textRect=QRect(this->width()-(text_width_spacing+text_max_width+text_width_spacing+icon_width+begin_width_spacing),begin_height_spacing,text_width_spacing+text_max_width+text_width_spacing,text_height_spacing+text_height+text_height_spacing);

        //畫文字
        QPen penText;
        penText.setColor(text_color);
        painter.setPen(penText);

        QTextOption option(Qt::AlignLeft | Qt::AlignVCenter);
        option.setWrapMode(QTextOption::WrapAtWordBoundaryOrAnywhere);
        painter.drawText(textRect, 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 ChatContentNoFrame::calc_text_size()
{
    QFontMetrics metrics = QFontMetrics(this->font());

    text_min_width=metrics.width("A")*2;

    qint32 min_width=begin_width_spacing+icon_width+text_width_spacing+text_width_spacing+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=metrics.height();
    }
    else
    {
        QRect textRect=QRect(0,0,text_max_width,0);
        int flags = Qt::TextWordWrap; // 自動換行
        textRect=metrics.boundingRect(textRect, flags, user_chat_content);
        text_height=textRect.height();
    }

    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;
}

 

效果

氣泡對話框3

#ifndef CHATCONTENTRECT_H
#define CHATCONTENTRECT_H

#include "userchatcontentinterface.h"

#include <QWidget>
#include <QPaintEvent>
#include <QColor>
#include <QString>
#include <QDateTime>

class ChatContentRect:public UserChatContentInterface
{
     Q_OBJECT
public:
    explicit ChatContentRect(QWidget *parent = 0);
    ~ChatContentRect();

    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);
    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_width_spacing;//文字距矩形邊框氣泡的邊框的寬度
    qint32 text_height_spacing;//文字距矩形氣泡邊框的高度
    qint32 triangle_width;//橫向三角形的寬度
    qint32 triangle_height;//橫向三角形的高度
    qint32 triangle_height_spacing;//橫向三角形距圓角邊框氣泡的邊框的高度


    QColor framework_border_color;//氣泡樣式的邊框顏色
    QColor framework_background_color;//氣泡樣式的背景顏色
    QColor text_color;//文字顏色
    QColor time_color;//時間顏色
};

#endif // CHATCONTENTRECT_H
#include "chatcontentrect.h"
#include <QPainter>
#include <QRect>
#include <QPen>
#include <QTextOption>
#include <QFont>
#include <QColor>
#include <QFontMetricsF>
#include <QDebug>
#include <QLinearGradient>

ChatContentRect::ChatContentRect(QWidget *parent):UserChatContentInterface(parent)
{
    this->setAttribute(Qt::WA_TranslucentBackground);//設置背景透明
    plug_name="rectangle 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_width_spacing=12;
    text_height_spacing=12;
    triangle_width=6;
    triangle_height=10;
    triangle_height_spacing=10;//最小爲10

    framework_border_color=QColor(180,180,180);   //設置顏色
    framework_background_color=QColor(244,164,96);
    text_color=QColor(56,56,56);
    time_color=QColor(153,153,153);

    QFont text_font = this->font();
    text_font.setFamily("新宋體");
    text_font.setPointSize(12);
    this->setFont(text_font);
}

ChatContentRect::~ChatContentRect()
{

}

QString ChatContentRect::getname()
{
    return this->plug_name;
}

qint32 ChatContentRect::getverison()
{
    return this->plug_version;
}

qint32 ChatContentRect::getwindowHeight()
{
    return this->window_height;
}

QString ChatContentRect::getuserIconName()
{
    return this->user_icon_name;
}

QString ChatContentRect::getuserChatContent()
{
    return this->user_chat_content;
}

QDateTime ChatContentRect::gettalkTime()
{
    return this->talk_time;
}

void ChatContentRect::setuserIconName(QString namestr)
{
    this->user_icon_name=namestr;
}

void ChatContentRect::setuserChatContent(QString usertext)
{
    this->user_chat_content=usertext;
    this->calc_text_size();
}

void ChatContentRect::settalkTime(QDateTime talktime)
{
    this->talk_time=talktime;
}

void ChatContentRect::run(show_type_enum type)
{
    show_type=type;
    this->update();
}

void ChatContentRect::paintEvent(QPaintEvent *event)
{
    QPainter painter(this);
    painter.setRenderHints(QPainter::Antialiasing | QPainter::SmoothPixmapTransform);//消鋸齒
    painter.setFont(this->font());

    if(this->show_type==SHOW_TYPE_LEFT)//左邊的圖像和內容顯示
    {
        //畫圖像
        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));

        //畫框架
        QRect bubbleRect=QRect(begin_width_spacing+icon_width,begin_height_spacing,triangle_width+text_width_spacing+text_max_width+text_width_spacing,text_height_spacing+text_height+text_height_spacing);
        //框,重疊後取邊
        painter.setPen(Qt::NoPen);
        painter.setBrush(QBrush(framework_border_color));
        painter.drawRoundedRect(bubbleRect.x()+triangle_width,bubbleRect.y(),bubbleRect.width()-triangle_width,bubbleRect.height(),18,18);
        //框,重疊後取框內
        QLinearGradient linearGradient(QPointF(bubbleRect.x()+triangle_width+1,bubbleRect.y()+1),QPointF(bubbleRect.x()+bubbleRect.width()-1,bubbleRect.y()+bubbleRect.height()-1));
        linearGradient.setColorAt(0,QColor(113,207,217));
        linearGradient.setColorAt(0.25,QColor(151,220,227));
        linearGradient.setColorAt(0.5,QColor(171,226,233));
        linearGradient.setColorAt(0.75,QColor(189,233,238));
        linearGradient.setColorAt(1,QColor(211,240,243));

        painter.setBrush(linearGradient);
        painter.drawRoundedRect(bubbleRect.x()+triangle_width+1,bubbleRect.y()+1,bubbleRect.width()-triangle_width-2,bubbleRect.height()-2,18,18);

        //三角,重疊後取框內
        QPointF points[3] = {
            QPointF(bubbleRect.x(), bubbleRect.y()+triangle_height_spacing-4),
            QPointF(bubbleRect.x()+triangle_width+1, bubbleRect.y()+triangle_height_spacing),
            QPointF(bubbleRect.x()+triangle_width+1, bubbleRect.y()+triangle_height_spacing+triangle_height),
        };
        painter.setPen(QPen(framework_background_color));
        painter.drawPolygon(points, 3);

        //畫三角的兩個邊
        painter.setPen(QPen(framework_border_color));
        painter.drawLine(QPointF(bubbleRect.x(), bubbleRect.y()+triangle_height_spacing-4), QPointF(bubbleRect.x()+triangle_width, bubbleRect.y()+triangle_height_spacing));
        painter.drawLine(QPointF(bubbleRect.x(), bubbleRect.y()+triangle_height_spacing-4), QPointF(bubbleRect.x()+triangle_width, bubbleRect.y()+triangle_height_spacing+triangle_height));

        //畫眼睛1
        painter.setPen(QPen(framework_border_color));
        painter.setBrush(QBrush(QColor(189,233,238)));
        QRectF arcrect1(bubbleRect.x()+bubbleRect.width()-begin_height_spacing*1.5, bubbleRect.y()-begin_height_spacing/2, begin_height_spacing/2, begin_height_spacing);
        painter.drawEllipse(arcrect1);
        painter.setBrush(QBrush(QColor(255,0,0)));
        QRectF cirrect1(bubbleRect.x()+bubbleRect.width()-begin_height_spacing*1.5+begin_height_spacing/8, bubbleRect.y()-begin_height_spacing/4, begin_height_spacing/4, begin_height_spacing/4);
        painter.drawEllipse(cirrect1);

        //畫眼睛2
        painter.setPen(QPen(framework_border_color));
        painter.setBrush(QBrush(QColor(189,233,238)));
        QRectF arcrect2(bubbleRect.x()+bubbleRect.width()-begin_height_spacing, bubbleRect.y()-begin_height_spacing/2, begin_height_spacing/2, begin_height_spacing);
        painter.drawEllipse(arcrect2);
        painter.setBrush(QBrush(QColor(255,0,0)));
        QRectF cirrect2(bubbleRect.x()+bubbleRect.width()-begin_height_spacing+begin_height_spacing/8, bubbleRect.y()-begin_height_spacing/4, begin_height_spacing/4, begin_height_spacing/4);
        painter.drawEllipse(cirrect2);

        //畫文字
        QPen penText;
        penText.setColor(text_color);
        painter.setPen(penText);

        QTextOption option(Qt::AlignLeft | Qt::AlignVCenter);
        option.setWrapMode(QTextOption::WrapAtWordBoundaryOrAnywhere);
        painter.drawText(QRect(bubbleRect.x()+triangle_width+text_width_spacing,bubbleRect.y()+text_height_spacing,text_max_width,text_height), user_chat_content,option);
    }
    else if(this->show_type==SHOW_TYPE_RIGHT)//右邊的圖像和內容顯示
    {
        //畫圖像
        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));

        //畫框架
        QRect bubbleRect=QRect(this->width()-(triangle_width+text_width_spacing+text_max_width+text_width_spacing+icon_width+begin_width_spacing),begin_height_spacing,triangle_width+text_width_spacing+text_max_width+text_width_spacing,text_height_spacing+text_height+text_height_spacing);
        //框,重疊後取邊
        painter.setPen(Qt::NoPen);
        painter.setBrush(QBrush(framework_border_color));
        painter.drawRoundedRect(bubbleRect.x(),bubbleRect.y(),bubbleRect.width()-triangle_width,bubbleRect.height(),18,18);

        //框,重疊後取框內
        QLinearGradient linearGradient(QPointF(bubbleRect.x()+triangle_width+1,bubbleRect.y()+1),QPointF(bubbleRect.x()+bubbleRect.width()-1,bubbleRect.y()+bubbleRect.height()-1));
        linearGradient.setColorAt(0,QColor(113,207,217));
        linearGradient.setColorAt(0.25,QColor(151,220,227));
        linearGradient.setColorAt(0.5,QColor(171,226,233));
        linearGradient.setColorAt(0.75,QColor(189,233,238));
        linearGradient.setColorAt(1,QColor(211,240,243));

        painter.setBrush(linearGradient);
        painter.drawRoundedRect(bubbleRect.x()+1,bubbleRect.y()+1,bubbleRect.width()-triangle_width-2,bubbleRect.height()-2,18,18);

        //三角,重疊後取框內
        QPointF points[3] = {
            QPointF(bubbleRect.x()+bubbleRect.width(), bubbleRect.y()+triangle_height_spacing-4),
            QPointF(bubbleRect.x()+bubbleRect.width()-triangle_width-1, bubbleRect.y()+triangle_height_spacing),
            QPointF(bubbleRect.x()+bubbleRect.width()-triangle_width-1, bubbleRect.y()+triangle_height_spacing+triangle_height),
        };
        painter.setPen(QPen(framework_background_color));
        painter.drawPolygon(points, 3);

        //畫三角的兩個邊
        painter.setPen(QPen(framework_border_color));
        painter.drawLine(QPointF(bubbleRect.x()+bubbleRect.width(), bubbleRect.y()+triangle_height_spacing-4), QPointF(bubbleRect.x()+bubbleRect.width()-triangle_width-1, bubbleRect.y()+triangle_height_spacing));
        painter.drawLine(QPointF(bubbleRect.x()+bubbleRect.width(), bubbleRect.y()+triangle_height_spacing-4), QPointF(bubbleRect.x()+bubbleRect.width()-triangle_width-1, bubbleRect.y()+triangle_height_spacing+triangle_height));

        //畫眼睛1
        painter.setPen(QPen(QColor(113,207,217)));
        painter.setBrush(QBrush(QColor(189,233,238)));
        QRectF arcrect1(bubbleRect.x()+begin_height_spacing*1.5, bubbleRect.y()-begin_height_spacing/2, begin_height_spacing/2, begin_height_spacing);
        painter.drawEllipse(arcrect1);
        painter.setBrush(QBrush(QColor(255,0,0)));
        QRectF cirrect1(bubbleRect.x()+begin_height_spacing*1.5+begin_height_spacing/4, bubbleRect.y()-begin_height_spacing/4, begin_height_spacing/4, begin_height_spacing/4);
        painter.drawEllipse(cirrect1);

        //畫眼睛2
        painter.setPen(QPen(QColor(113,207,217)));
        painter.setBrush(QBrush(QColor(189,233,238)));
        QRectF arcrect2(bubbleRect.x()+begin_height_spacing, bubbleRect.y()-begin_height_spacing/2, begin_height_spacing/2, begin_height_spacing);
        painter.drawEllipse(arcrect2);
        painter.setBrush(QBrush(QColor(255,0,0)));
        QRectF cirrect2(bubbleRect.x()+begin_height_spacing+begin_height_spacing/4, bubbleRect.y()-begin_height_spacing/4, begin_height_spacing/4, begin_height_spacing/4);
        painter.drawEllipse(cirrect2);

        //畫文字
        QPen penText;
        penText.setColor(text_color);
        painter.setPen(penText);

        QTextOption option(Qt::AlignLeft | Qt::AlignVCenter);
        option.setWrapMode(QTextOption::WrapAtWordBoundaryOrAnywhere);
        painter.drawText(QRect(bubbleRect.x()+text_width_spacing,bubbleRect.y()+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 ChatContentRect::calc_text_size()
{
    QFontMetrics metrics = QFontMetrics(this->font());

    text_min_width=metrics.width("A")*2+begin_height_spacing*1.5>text_width_spacing? begin_height_spacing*1.5-text_width_spacing : 0;

    qint32 min_width=begin_width_spacing+icon_width+triangle_width+text_width_spacing+text_width_spacing+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>triangle_height_spacing+triangle_height+triangle_height_spacing? metrics.height() : triangle_height_spacing+triangle_height+triangle_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=textRect.height();
    }

    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;
}

 

效果

氣泡對話框4

#ifndef CHATCONTENTROUND_H
#define CHATCONTENTROUND_H

#include "userchatcontentinterface.h"

#include <QWidget>
#include <QPaintEvent>
#include <QColor>
#include <QString>
#include <QDateTime>

class ChatContentRound :public UserChatContentInterface
{
    Q_OBJECT
public:
    explicit ChatContentRound(QWidget *parent = 0);
    ~ChatContentRound();

    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);
    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_width_spacing;//文字距圓角邊框氣泡的邊框的寬度
    qint32 text_height_spacing;//文字距圓角氣泡邊框的高度
    qint32 triangle_width;//橫向三角形的寬度
    qint32 triangle_height;//橫向三角形的高度
    qint32 triangle_height_spacing;//橫向三角形距圓角邊框氣泡的邊框的高度


    QColor framework_border_color;//氣泡樣式的邊框顏色
    QColor framework_background_color;//氣泡樣式的背景顏色
    QColor text_color;//文字顏色
    QColor time_color;//時間顏色
};

#endif // CHATCONTENTROUND_H
#include "chatcontentround.h"
#include <QPainter>
#include <QRect>
#include <QPen>
#include <QTextOption>
#include <QFont>
#include <QColor>
#include <QFontMetricsF>
#include <QDebug>

ChatContentRound::ChatContentRound(QWidget *parent):UserChatContentInterface(parent)
{
    //this->setAttribute(Qt::WA_TranslucentBackground);//設置背景透明
    plug_name="round rectangle chat content";  //設置插件信息
    plug_version=1.0;

    show_type=SHOW_TYPE_MIN;  //設置變量的初始值
    window_height=10;
    begin_width_spacing=20;
    begin_height_spacing=10;
    icon_width=40;
    icon_height=40;
    text_width_spacing=12;
    text_height_spacing=10;
    triangle_width=6;
    triangle_height=10;
    triangle_height_spacing=10;

    QFont text_font = this->font();
    text_font.setFamily("新宋體");
    text_font.setPointSize(10);
    this->setFont(text_font);
}

ChatContentRound::~ChatContentRound()
{

}

QString ChatContentRound::getname()
{
    return this->plug_name;
}

qint32 ChatContentRound::getverison()
{
    return this->plug_version;
}

qint32 ChatContentRound::getwindowHeight()
{
    return this->window_height;
}

QString ChatContentRound::getuserIconName()
{
    return this->user_icon_name;
}

QString ChatContentRound::getuserChatContent()
{
    return this->user_chat_content;
}

QDateTime ChatContentRound::gettalkTime()
{
    return this->talk_time;
}

void ChatContentRound::setuserIconName(QString namestr)
{
    this->user_icon_name=namestr;
}

void ChatContentRound::setuserChatContent(QString usertext)
{
    this->user_chat_content=usertext;
    this->calc_text_size();
}

void ChatContentRound::settalkTime(QDateTime talktime)
{
    this->talk_time=talktime;
}

void ChatContentRound::run(show_type_enum type)
{
    show_type=type;
    this->update();
}

void ChatContentRound::paintEvent(QPaintEvent *event)
{
    QPainter painter(this);
    painter.setRenderHints(QPainter::Antialiasing | QPainter::SmoothPixmapTransform);//消鋸齒
    painter.setFont(this->font());

    if(this->show_type==SHOW_TYPE_LEFT)//左邊的圖像和內容顯示
    {
        //畫圖像
        framework_border_color=QColor(195, 195, 195);   //設置顏色
        framework_background_color=QColor(255,255,255);
        text_color=QColor(0,0,0);
        time_color=QColor(153,153,153);
        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));
        //畫框架
        QRect bubbleRect=QRect(begin_width_spacing+icon_width,begin_height_spacing,triangle_width+text_width_spacing+text_max_width+text_width_spacing,text_height_spacing+text_height+text_height_spacing);
        //框,重疊後取邊
        painter.setPen(Qt::NoPen);
        painter.setBrush(QBrush(framework_border_color));
        painter.drawRoundedRect(bubbleRect.x()+triangle_width,bubbleRect.y(),bubbleRect.width()-triangle_width,bubbleRect.height(),8,8);
        //框,重疊後取框內
        painter.setBrush(QBrush(framework_background_color));
        painter.drawRoundedRect(bubbleRect.x()+triangle_width+1,bubbleRect.y()+1,bubbleRect.width()-triangle_width-2,bubbleRect.height()-2,8,8);

        //三角,重疊後取框內
        QPointF points[3] = {
            QPointF(bubbleRect.x(), bubbleRect.y()+triangle_height_spacing+triangle_height/2),
            QPointF(bubbleRect.x()+triangle_width+1, bubbleRect.y()+triangle_height_spacing),
            QPointF(bubbleRect.x()+triangle_width+1, bubbleRect.y()+triangle_height_spacing+triangle_height),
        };
        painter.setPen(QPen(framework_background_color));
        painter.drawPolygon(points, 3);

        //畫三角的兩個邊
        painter.setPen(QPen(framework_border_color));
        painter.drawLine(QPointF(bubbleRect.x(), bubbleRect.y()+triangle_height_spacing+triangle_height/2), QPointF(bubbleRect.x()+triangle_width, bubbleRect.y()+triangle_height_spacing));
        painter.drawLine(QPointF(bubbleRect.x(), bubbleRect.y()+triangle_height_spacing+triangle_height/2), QPointF(bubbleRect.x()+triangle_width, bubbleRect.y()+triangle_height_spacing+triangle_height));
        //text
        QPen penText;
        penText.setColor(text_color);
        painter.setPen(penText);
        QTextOption option(Qt::AlignLeft | Qt::AlignVCenter);
        option.setWrapMode(QTextOption::WrapAtWordBoundaryOrAnywhere);
        painter.drawText(QRect(bubbleRect.x()+triangle_width+text_width_spacing,bubbleRect.y()+text_height_spacing,text_max_width,text_height), user_chat_content,option);
    }
    else if(this->show_type==SHOW_TYPE_RIGHT)//右邊的圖像和內容顯示
    {
        //icon
        framework_border_color=QColor(195, 195, 195);   //設置顏色
        framework_background_color=QColor(158,234,106);
        text_color=QColor(0,0,0);
        time_color=QColor(153,153,153);
        this->calc_text_size();
        QRect icon_rect=QRect(this->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));
        //framework
        QRect bubbleRect=QRect(this->width()-(triangle_width+text_width_spacing+text_max_width+text_width_spacing+icon_width+begin_width_spacing),begin_height_spacing,triangle_width+text_width_spacing+text_max_width+text_width_spacing,text_height_spacing+text_height+text_height_spacing);

        //框,重疊後取邊
        painter.setPen(Qt::NoPen);
        painter.setBrush(QBrush(framework_border_color));
        painter.drawRoundedRect(bubbleRect.x(),bubbleRect.y(),bubbleRect.width()-triangle_width,bubbleRect.height(),8,8);
        //框,重疊後取框內
        painter.setBrush(QBrush(framework_background_color));
        painter.drawRoundedRect(bubbleRect.x()+1,bubbleRect.y()+1,bubbleRect.width()-triangle_width-2,bubbleRect.height()-2,8,8);

        //三角,重疊後取框內
        QPointF points[3] = {
            QPointF(bubbleRect.x()+bubbleRect.width(), bubbleRect.y()+triangle_height_spacing+triangle_height/2),
            QPointF(bubbleRect.x()+bubbleRect.width()-triangle_width-1, bubbleRect.y()+triangle_height_spacing),
            QPointF(bubbleRect.x()+bubbleRect.width()-triangle_width-1, bubbleRect.y()+triangle_height_spacing+triangle_height),
        };
        painter.setPen(QPen(framework_background_color));
        painter.drawPolygon(points, 3);

        //畫三角的兩個邊
        painter.setPen(QPen(framework_border_color));
        painter.drawLine(QPointF(bubbleRect.x()+bubbleRect.width(), bubbleRect.y()+triangle_height_spacing+triangle_height/2), QPointF(bubbleRect.x()+bubbleRect.width()-triangle_width, bubbleRect.y()+triangle_height_spacing));
        painter.drawLine(QPointF(bubbleRect.x()+bubbleRect.width(), bubbleRect.y()+triangle_height_spacing+triangle_height/2), QPointF(bubbleRect.x()+bubbleRect.width()-triangle_width, bubbleRect.y()+triangle_height_spacing+triangle_height));

        //text
        QPen penText;
        penText.setColor(text_color);
        painter.setPen(penText);
        QTextOption option(Qt::AlignLeft | Qt::AlignVCenter);
        option.setWrapMode(QTextOption::WrapAtWordBoundaryOrAnywhere);
        painter.drawText(QRect(bubbleRect.x()+text_width_spacing,bubbleRect.y()+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 ChatContentRound::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+text_width_spacing+text_width_spacing+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>triangle_height_spacing+triangle_height+triangle_height_spacing? metrics.height() : triangle_height_spacing+triangle_height+triangle_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=textRect.height();
    }
    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;
}

效果

氣泡對話框5 

#ifndef CHATCONTENTTRIANGLE_H
#define CHATCONTENTRECT_H

#include "userchatcontentinterface.h"

#include <QWidget>
#include <QPaintEvent>
#include <QColor>
#include <QString>
#include <QDateTime>

class ChatContentTriangle:public UserChatContentInterface
{
     Q_OBJECT
public:
    explicit ChatContentTriangle(QWidget *parent = 0);
    ~ChatContentTriangle();

    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);
    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 frame_width_spacing;//圖像與框架間隔寬度

    qint32 triangle_width;//豎向三角形的寬度
    qint32 triangle_height;//豎向三角形的高度
    qint32 rect_radius;
    qint32 circle_radius;


    QColor framework_border_color;//氣泡樣式的邊框顏色
    QColor framework_background_color;//氣泡樣式的背景顏色
    QColor text_color;//文字顏色
    QColor time_color;//時間顏色
};

#endif // CHATCONTENTRECT_H
#include "chatcontenttriangle.h"
#include <QPainter>
#include <QRect>
#include <QPen>
#include <QTextOption>
#include <QFont>
#include <QColor>
#include <QFontMetricsF>
#include <QDebug>
#include <QPainterPath>

ChatContentTriangle::ChatContentTriangle(QWidget *parent):UserChatContentInterface(parent)
{
    this->setAttribute(Qt::WA_TranslucentBackground);//設置背景透明
    plug_name="no 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;
    frame_width_spacing=6;

    triangle_width=12;
    triangle_height=8;

    rect_radius=16;
    circle_radius=12;

    text_color=QColor(0,128,128);
    time_color=QColor(153,153,153);

    QFont text_font = this->font();
    text_font.setFamily("黑體");
    text_font.setPointSize(12);
    this->setFont(text_font);
}

ChatContentTriangle::~ChatContentTriangle()
{

}

QString ChatContentTriangle::getname()
{
    return this->plug_name;
}

qint32 ChatContentTriangle::getverison()
{
    return this->plug_version;
}

qint32 ChatContentTriangle::getwindowHeight()
{
    return this->window_height;
}

QString ChatContentTriangle::getuserIconName()
{
    return this->user_icon_name;
}

QString ChatContentTriangle::getuserChatContent()
{
    return this->user_chat_content;
}

QDateTime ChatContentTriangle::gettalkTime()
{
    return this->talk_time;
}

void ChatContentTriangle::setuserIconName(QString namestr)
{
    this->user_icon_name=namestr;
}

void ChatContentTriangle::setuserChatContent(QString usertext)
{
    this->user_chat_content=usertext;
    this->calc_text_size();
}

void ChatContentTriangle::settalkTime(QDateTime talktime)
{
    this->talk_time=talktime;
}

void ChatContentTriangle::run(show_type_enum type)
{
    show_type=type;
    this->update();
}

void ChatContentTriangle::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(0,128,128);
        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));

        //畫框架1
        QPainterPath bubble_path_1;
        bubble_path_1.moveTo(begin_width_spacing+icon_width+frame_width_spacing+rect_radius,begin_height_spacing+triangle_height);
        bubble_path_1.arcTo(begin_width_spacing+icon_width+frame_width_spacing, begin_height_spacing+triangle_height, rect_radius*2, rect_radius*2, 90.0f, 90.0f);
        bubble_path_1.lineTo(begin_width_spacing+icon_width+frame_width_spacing,begin_height_spacing+triangle_height+rect_radius/2+circle_radius+text_height+rect_radius/2-rect_radius);
        bubble_path_1.arcTo(begin_width_spacing+icon_width+frame_width_spacing, begin_height_spacing+triangle_height+rect_radius/2+circle_radius+text_height+rect_radius/2-rect_radius*2, rect_radius*2, rect_radius*2, 180.0f, 90.0f);
        bubble_path_1.lineTo(begin_width_spacing+icon_width+frame_width_spacing+rect_radius/2+circle_radius*2+text_max_width+circle_radius*2-rect_radius/2,begin_height_spacing+triangle_height+rect_radius/2+circle_radius+text_height+rect_radius/2);
        bubble_path_1.arcTo(begin_width_spacing+icon_width+frame_width_spacing+rect_radius/2+circle_radius*2+text_max_width+circle_radius*2-rect_radius-rect_radius/2, begin_height_spacing+triangle_height+rect_radius/2+circle_radius+text_height+rect_radius/2 - rect_radius*2, rect_radius*2, rect_radius*2, 270.0f, 90.0f);
        bubble_path_1.lineTo(begin_width_spacing+icon_width+frame_width_spacing+rect_radius/2+circle_radius*2+text_max_width+circle_radius*2+rect_radius/2,begin_height_spacing+triangle_height+rect_radius);
        bubble_path_1.arcTo(begin_width_spacing+icon_width+frame_width_spacing+rect_radius/2+circle_radius*2+text_max_width+circle_radius*2+rect_radius/2-rect_radius*2, begin_height_spacing+triangle_height, rect_radius*2, rect_radius*2, 0.0f, 90.0f);
        bubble_path_1.lineTo(begin_width_spacing+icon_width+frame_width_spacing+rect_radius/2+circle_radius*2+text_max_width+circle_radius*2-rect_radius/2-triangle_width/2,begin_height_spacing);
        bubble_path_1.lineTo(begin_width_spacing+icon_width+frame_width_spacing+rect_radius/2+circle_radius*2+text_max_width+circle_radius*2-rect_radius/2-triangle_width,begin_height_spacing+triangle_height);
        bubble_path_1.lineTo(begin_width_spacing+icon_width+frame_width_spacing+rect_radius+triangle_width,begin_height_spacing+triangle_height);
        bubble_path_1.lineTo(begin_width_spacing+icon_width+frame_width_spacing+rect_radius+triangle_width/2,begin_height_spacing);
        bubble_path_1.lineTo(begin_width_spacing+icon_width+frame_width_spacing+rect_radius,begin_height_spacing+triangle_height);
        QPen pen_1(QColor(72,94,108));
        pen_1.setWidth(3);
        painter.setPen(pen_1);
        painter.setBrush(QBrush(QColor(255,235,210)));
        painter.drawPath(bubble_path_1);

        //畫圓角三角形
        qint32 tt_spacing=4;

        QPainterPath bubble_path_2;
        bubble_path_2.moveTo(begin_width_spacing+icon_width+frame_width_spacing+rect_radius/2+circle_radius*2+text_max_width+circle_radius*2+rect_radius/2-tt_spacing,begin_height_spacing+triangle_height+(circle_radius+rect_radius/2)*2);
        bubble_path_2.lineTo(begin_width_spacing+icon_width+frame_width_spacing+rect_radius/2+circle_radius*2+text_max_width+circle_radius*2+rect_radius/2-tt_spacing,begin_height_spacing+triangle_height+rect_radius);
        bubble_path_2.arcTo(begin_width_spacing+icon_width+frame_width_spacing+rect_radius/2+circle_radius*2+text_max_width+circle_radius*2+rect_radius/2-tt_spacing - (rect_radius-tt_spacing)*2, begin_height_spacing+triangle_height+tt_spacing, (rect_radius-tt_spacing)*2, (rect_radius-tt_spacing)*2, 0.0f, 90.0f);
        bubble_path_2.lineTo(begin_width_spacing+icon_width+frame_width_spacing+rect_radius/2+circle_radius*2+text_max_width+circle_radius*2+rect_radius/2-(circle_radius+rect_radius/2)*2,begin_height_spacing+triangle_height+tt_spacing);
        bubble_path_2.lineTo(begin_width_spacing+icon_width+frame_width_spacing+rect_radius/2+circle_radius*2+text_max_width+circle_radius*2+rect_radius/2-tt_spacing,begin_height_spacing+triangle_height+(circle_radius+rect_radius/2)*2);
        QPen pen_2(QColor(163,113,42));
        painter.setPen(pen_2);
        painter.setBrush(QBrush(QColor(163,113,42)));
        painter.drawPath(bubble_path_2);

        //畫框架2
        QPainterPath bubble_path_3;
        bubble_path_3.moveTo(begin_width_spacing+icon_width+frame_width_spacing+rect_radius,begin_height_spacing+triangle_height+tt_spacing);
        bubble_path_3.arcTo(begin_width_spacing+icon_width+frame_width_spacing+tt_spacing, begin_height_spacing+triangle_height+tt_spacing, (rect_radius-tt_spacing)*2, (rect_radius-tt_spacing)*2, 90.0f, 90.0f);
        bubble_path_3.lineTo(begin_width_spacing+icon_width+frame_width_spacing+tt_spacing,begin_height_spacing+triangle_height+rect_radius/2+circle_radius+text_height+rect_radius/2-rect_radius);
        bubble_path_3.arcTo(begin_width_spacing+icon_width+frame_width_spacing+tt_spacing, begin_height_spacing+triangle_height+rect_radius/2+circle_radius+text_height+rect_radius/2-rect_radius-(rect_radius-tt_spacing), (rect_radius-tt_spacing)*2, (rect_radius-tt_spacing)*2, 180.0f, 90.0f);
        bubble_path_3.lineTo(begin_width_spacing+icon_width+frame_width_spacing+rect_radius/2+circle_radius*2+text_max_width+circle_radius*2-rect_radius/2,begin_height_spacing+triangle_height+rect_radius/2+circle_radius+text_height+rect_radius/2-tt_spacing);
        bubble_path_3.arcTo(begin_width_spacing+icon_width+frame_width_spacing+rect_radius/2+circle_radius*2+text_max_width+circle_radius*2-rect_radius/2 - (rect_radius-tt_spacing), begin_height_spacing+triangle_height+rect_radius/2+circle_radius+text_height+rect_radius/2-rect_radius-(rect_radius-tt_spacing), (rect_radius-tt_spacing)*2, (rect_radius-tt_spacing)*2, 270.0f, 90.0f);
        bubble_path_3.lineTo(begin_width_spacing+icon_width+frame_width_spacing+rect_radius/2+circle_radius*2+text_max_width+circle_radius*2+rect_radius/2-tt_spacing,begin_height_spacing+triangle_height+rect_radius);
        bubble_path_3.arcTo(begin_width_spacing+icon_width+frame_width_spacing+rect_radius/2+circle_radius*2+text_max_width+circle_radius*2+rect_radius/2-tt_spacing - (rect_radius-tt_spacing)*2, begin_height_spacing+triangle_height+tt_spacing, (rect_radius-tt_spacing)*2, (rect_radius-tt_spacing)*2, 0.0f, 90.0f);
        bubble_path_3.lineTo(begin_width_spacing+icon_width+frame_width_spacing+rect_radius/2+circle_radius*2+text_max_width+circle_radius*2-rect_radius/2-triangle_width/2,begin_height_spacing+tt_spacing);
        bubble_path_3.lineTo(begin_width_spacing+icon_width+frame_width_spacing+rect_radius/2+circle_radius*2+text_max_width+circle_radius*2-rect_radius/2-triangle_width,begin_height_spacing+triangle_height+tt_spacing);
        bubble_path_3.lineTo(begin_width_spacing+icon_width+frame_width_spacing+rect_radius+triangle_width,begin_height_spacing+triangle_height+tt_spacing);
        bubble_path_3.lineTo(begin_width_spacing+icon_width+frame_width_spacing+rect_radius+triangle_width/2,begin_height_spacing+tt_spacing);
        bubble_path_3.lineTo(begin_width_spacing+icon_width+frame_width_spacing+rect_radius,begin_height_spacing+triangle_height+tt_spacing);

        QPen pen_3(QColor(150,150,150));
        pen_3.setStyle(Qt::DashLine);
        painter.setPen(pen_3);
        painter.setBrush(Qt::NoBrush);
        painter.drawPath(bubble_path_3);

        //畫圓
        QPen pen_4(QColor(255,255,255));
        painter.setPen(pen_4);
        painter.setBrush(QBrush(QColor(255,255,255)));
        painter.drawEllipse(QRect(begin_width_spacing+icon_width+frame_width_spacing+rect_radius/2,begin_height_spacing+triangle_height+rect_radius/2,circle_radius*2,circle_radius*2));
        painter.drawEllipse(QRect(begin_width_spacing+icon_width+frame_width_spacing+rect_radius/2+circle_radius*2+text_max_width,begin_height_spacing+triangle_height+rect_radius/2,circle_radius*2,circle_radius*2));

        QPen pen_5(QColor(0,0,0));
        painter.setPen(pen_5);
        painter.setBrush(QBrush(QColor(0,0,0)));
        painter.drawEllipse(QRect(begin_width_spacing+icon_width+frame_width_spacing+rect_radius/2+circle_radius/3,begin_height_spacing+triangle_height+rect_radius/2+circle_radius/3,circle_radius*4/3,circle_radius*4/3));
        painter.drawEllipse(QRect(begin_width_spacing+icon_width+frame_width_spacing+rect_radius/2+circle_radius*2+text_max_width+circle_radius/3,begin_height_spacing+triangle_height+rect_radius/2+circle_radius/3,circle_radius*4/3,circle_radius*4/3));

        QPen pen_6(QColor(236,117,109));
        painter.setPen(pen_6);
        painter.setBrush(QBrush(QColor(236,117,109)));
        painter.drawRoundRect(QRect(begin_width_spacing+icon_width+frame_width_spacing+rect_radius/2,begin_height_spacing+triangle_height+rect_radius/2+circle_radius*2+2,circle_radius*2,4),4,4);
        painter.drawRoundRect(QRect(begin_width_spacing+icon_width+frame_width_spacing+rect_radius/2+circle_radius*2+text_max_width,begin_height_spacing+triangle_height+rect_radius/2+circle_radius*2+2,circle_radius*2,4),4,4);

        //畫文字
        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+frame_width_spacing+rect_radius/2+circle_radius*2,begin_height_spacing+triangle_height+rect_radius/2+circle_radius,text_max_width,text_height), user_chat_content,option);
    }
    else if(this->show_type==SHOW_TYPE_RIGHT)//右邊的圖像和內容顯示
    {
        //畫圖像
        text_color=QColor(0,128,64);
        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));

        //畫框架1
        QPainterPath bubble_path_1;
        bubble_path_1.moveTo(window_current_width-(begin_width_spacing+icon_width+frame_width_spacing+rect_radius),begin_height_spacing+triangle_height);
        bubble_path_1.arcTo(window_current_width-(begin_width_spacing+icon_width+frame_width_spacing+rect_radius*2), begin_height_spacing+triangle_height, rect_radius*2, rect_radius*2, 90.0f, -90.0f);
        bubble_path_1.lineTo(window_current_width-(begin_width_spacing+icon_width+frame_width_spacing),begin_height_spacing+triangle_height+rect_radius/2+circle_radius+text_height+rect_radius/2-rect_radius);
        bubble_path_1.arcTo(window_current_width-(begin_width_spacing+icon_width+frame_width_spacing+rect_radius*2), begin_height_spacing+triangle_height+rect_radius/2+circle_radius+text_height+rect_radius/2-rect_radius*2, rect_radius*2, rect_radius*2, 0.0f, -90.0f);
        bubble_path_1.lineTo(window_current_width-(begin_width_spacing+icon_width+frame_width_spacing+rect_radius/2+circle_radius*2+text_max_width+circle_radius*2-rect_radius/2),begin_height_spacing+triangle_height+rect_radius/2+circle_radius+text_height+rect_radius/2);
        bubble_path_1.arcTo(window_current_width-(begin_width_spacing+icon_width+frame_width_spacing+rect_radius/2+circle_radius*2+text_max_width+circle_radius*2+rect_radius/2), begin_height_spacing+triangle_height+rect_radius/2+circle_radius+text_height+rect_radius/2 - rect_radius*2, rect_radius*2, rect_radius*2, 270.0f, -90.0f);
        bubble_path_1.lineTo(window_current_width-(begin_width_spacing+icon_width+frame_width_spacing+rect_radius/2+circle_radius*2+text_max_width+circle_radius*2+rect_radius/2),begin_height_spacing+triangle_height+rect_radius);
        bubble_path_1.arcTo(window_current_width-(begin_width_spacing+icon_width+frame_width_spacing+rect_radius/2+circle_radius*2+text_max_width+circle_radius*2+rect_radius/2), begin_height_spacing+triangle_height, rect_radius*2, rect_radius*2, 180.0f, -90.0f);

        bubble_path_1.lineTo(window_current_width-(begin_width_spacing+icon_width+frame_width_spacing+rect_radius/2+circle_radius*2+text_max_width+circle_radius*2+rect_radius/2-rect_radius-triangle_width/2),begin_height_spacing);
        bubble_path_1.lineTo(window_current_width-(begin_width_spacing+icon_width+frame_width_spacing+rect_radius/2+circle_radius*2+text_max_width+circle_radius*2-rect_radius/2-triangle_width),begin_height_spacing+triangle_height);
        bubble_path_1.lineTo(window_current_width-(begin_width_spacing+icon_width+frame_width_spacing+rect_radius+triangle_width),begin_height_spacing+triangle_height);
        bubble_path_1.lineTo(window_current_width-(begin_width_spacing+icon_width+frame_width_spacing+rect_radius+triangle_width/2),begin_height_spacing);
        bubble_path_1.lineTo(window_current_width-(begin_width_spacing+icon_width+frame_width_spacing+rect_radius),begin_height_spacing+triangle_height);
        QPen pen_1(QColor(72,94,108));
        pen_1.setWidth(3);
        painter.setPen(pen_1);
        painter.setBrush(QBrush(QColor(255,235,210)));
        painter.drawPath(bubble_path_1);

        //畫圓角三角形
        qint32 tt_spacing=4;

        QPainterPath bubble_path_2;
        bubble_path_2.moveTo(window_current_width-(begin_width_spacing+icon_width+frame_width_spacing+rect_radius/2+circle_radius*2+text_max_width+circle_radius*2+rect_radius/2-tt_spacing),begin_height_spacing+triangle_height+(circle_radius+rect_radius/2)*2);
        bubble_path_2.lineTo(window_current_width-(begin_width_spacing+icon_width+frame_width_spacing+rect_radius/2+circle_radius*2+text_max_width+circle_radius*2+rect_radius/2-tt_spacing),begin_height_spacing+triangle_height+rect_radius);
        bubble_path_2.arcTo(window_current_width-(begin_width_spacing+icon_width+frame_width_spacing+rect_radius/2+circle_radius*2+text_max_width+circle_radius*2+rect_radius/2-tt_spacing), begin_height_spacing+triangle_height+tt_spacing, (rect_radius-tt_spacing)*2, (rect_radius-tt_spacing)*2, 180.0f, -90.0f);
        bubble_path_2.lineTo(window_current_width-(begin_width_spacing+icon_width+frame_width_spacing+rect_radius/2+circle_radius*2+text_max_width+circle_radius*2+rect_radius/2-(circle_radius+rect_radius/2)*2),begin_height_spacing+triangle_height+tt_spacing);
        bubble_path_2.lineTo(window_current_width-(begin_width_spacing+icon_width+frame_width_spacing+rect_radius/2+circle_radius*2+text_max_width+circle_radius*2+rect_radius/2-tt_spacing),begin_height_spacing+triangle_height+(circle_radius+rect_radius/2)*2);
        QPen pen_2(QColor(163,113,42));
        painter.setPen(pen_2);
        painter.setBrush(QBrush(QColor(163,113,42)));
        painter.drawPath(bubble_path_2);

        //畫框架2
        QPainterPath bubble_path_3;
        bubble_path_3.moveTo(window_current_width-(begin_width_spacing+icon_width+frame_width_spacing+rect_radius),begin_height_spacing+triangle_height+tt_spacing);
        bubble_path_3.arcTo(window_current_width-(begin_width_spacing+icon_width+frame_width_spacing+tt_spacing+(rect_radius-tt_spacing)*2), begin_height_spacing+triangle_height+tt_spacing, (rect_radius-tt_spacing)*2, (rect_radius-tt_spacing)*2, 90.0f, -90.0f);
        bubble_path_3.lineTo(window_current_width-(begin_width_spacing+icon_width+frame_width_spacing+tt_spacing),begin_height_spacing+triangle_height+rect_radius/2+circle_radius+text_height+rect_radius/2-rect_radius);
        bubble_path_3.arcTo(window_current_width-(begin_width_spacing+icon_width+frame_width_spacing+tt_spacing+(rect_radius-tt_spacing)*2), begin_height_spacing+triangle_height+rect_radius/2+circle_radius+text_height+rect_radius/2-rect_radius-(rect_radius-tt_spacing), (rect_radius-tt_spacing)*2, (rect_radius-tt_spacing)*2, 0.0f, -90.0f);
        bubble_path_3.lineTo(window_current_width-(begin_width_spacing+icon_width+frame_width_spacing+rect_radius/2+circle_radius*2+text_max_width+circle_radius*2-rect_radius/2),begin_height_spacing+triangle_height+rect_radius/2+circle_radius+text_height+rect_radius/2-tt_spacing);
        bubble_path_3.arcTo(window_current_width-(begin_width_spacing+icon_width+frame_width_spacing+rect_radius/2+circle_radius*2+text_max_width+circle_radius*2+rect_radius/2-tt_spacing), begin_height_spacing+triangle_height+rect_radius/2+circle_radius+text_height+rect_radius/2-rect_radius-(rect_radius-tt_spacing), (rect_radius-tt_spacing)*2, (rect_radius-tt_spacing)*2, 270.0f, -90.0f);
        bubble_path_3.lineTo(window_current_width-(begin_width_spacing+icon_width+frame_width_spacing+rect_radius/2+circle_radius*2+text_max_width+circle_radius*2+rect_radius/2-tt_spacing),begin_height_spacing+triangle_height+rect_radius);
        bubble_path_3.arcTo(window_current_width-(begin_width_spacing+icon_width+frame_width_spacing+rect_radius/2+circle_radius*2+text_max_width+circle_radius*2+rect_radius/2-tt_spacing), begin_height_spacing+triangle_height+tt_spacing, (rect_radius-tt_spacing)*2, (rect_radius-tt_spacing)*2, 180.0f, -90.0f);
        bubble_path_3.lineTo(window_current_width-(begin_width_spacing+icon_width+frame_width_spacing+rect_radius/2+circle_radius*2+text_max_width+circle_radius*2-rect_radius/2-triangle_width/2),begin_height_spacing+tt_spacing);
        bubble_path_3.lineTo(window_current_width-(begin_width_spacing+icon_width+frame_width_spacing+rect_radius/2+circle_radius*2+text_max_width+circle_radius*2-rect_radius/2-triangle_width),begin_height_spacing+triangle_height+tt_spacing);
        bubble_path_3.lineTo(window_current_width-(begin_width_spacing+icon_width+frame_width_spacing+rect_radius+triangle_width),begin_height_spacing+triangle_height+tt_spacing);
        bubble_path_3.lineTo(window_current_width-(begin_width_spacing+icon_width+frame_width_spacing+rect_radius+triangle_width/2),begin_height_spacing+tt_spacing);
        bubble_path_3.lineTo(window_current_width-(begin_width_spacing+icon_width+frame_width_spacing+rect_radius),begin_height_spacing+triangle_height+tt_spacing);

        QPen pen_3(QColor(150,150,150));
        pen_3.setStyle(Qt::DashLine);
        painter.setPen(pen_3);
        painter.setBrush(Qt::NoBrush);
        painter.drawPath(bubble_path_3);

        //畫圓
        QPen pen_4(QColor(255,255,255));
        painter.setPen(pen_4);
        painter.setBrush(QBrush(QColor(255,255,255)));
        painter.drawEllipse(QRect(window_current_width-(begin_width_spacing+icon_width+frame_width_spacing+rect_radius/2+circle_radius*2),begin_height_spacing+triangle_height+rect_radius/2,circle_radius*2,circle_radius*2));
        painter.drawEllipse(QRect(window_current_width-(begin_width_spacing+icon_width+frame_width_spacing+rect_radius/2+circle_radius*2+text_max_width+circle_radius*2),begin_height_spacing+triangle_height+rect_radius/2,circle_radius*2,circle_radius*2));

        QPen pen_5(QColor(0,0,0));
        painter.setPen(pen_5);
        painter.setBrush(QBrush(QColor(0,0,0)));
        painter.drawEllipse(QRect(window_current_width-(begin_width_spacing+icon_width+frame_width_spacing+rect_radius/2+circle_radius/3+circle_radius*4/3),begin_height_spacing+triangle_height+rect_radius/2+circle_radius/3,circle_radius*4/3,circle_radius*4/3));
        painter.drawEllipse(QRect(window_current_width-(begin_width_spacing+icon_width+frame_width_spacing+rect_radius/2+circle_radius*2+text_max_width+circle_radius/3+circle_radius*4/3),begin_height_spacing+triangle_height+rect_radius/2+circle_radius/3,circle_radius*4/3,circle_radius*4/3));

        QPen pen_6(QColor(236,117,109));
        painter.setPen(pen_6);
        painter.setBrush(QBrush(QColor(236,117,109)));
        painter.drawRoundRect(QRect(window_current_width-(begin_width_spacing+icon_width+frame_width_spacing+rect_radius/2+circle_radius*2),begin_height_spacing+triangle_height+rect_radius/2+circle_radius*2+2,circle_radius*2,4),4,4);
        painter.drawRoundRect(QRect(window_current_width-(begin_width_spacing+icon_width+frame_width_spacing+rect_radius/2+circle_radius*2+text_max_width+circle_radius*2),begin_height_spacing+triangle_height+rect_radius/2+circle_radius*2+2,circle_radius*2,4),4,4);

        //畫文字
        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+frame_width_spacing+rect_radius/2+circle_radius*2+text_max_width),begin_height_spacing+triangle_height+rect_radius/2+circle_radius,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 ChatContentTriangle::calc_text_size()
{
    QFontMetrics metrics = QFontMetrics(this->font());

    text_min_width=metrics.width("A")*2;

    qint32 min_width=begin_width_spacing+icon_width+frame_width_spacing+rect_radius/2+circle_radius*2+circle_radius*2+rect_radius/2+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=rect_radius/2+circle_radius+metrics.height()+rect_radius/2>(rect_radius/2+circle_radius)*2+rect_radius? metrics.height(): (rect_radius/2+circle_radius)+rect_radius ;
    }
    else
    {
        QRect textRect=QRect(0,0,text_max_width,0);
        int flags = Qt::TextWordWrap; // 自動換行
        textRect=metrics.boundingRect(textRect, flags, user_chat_content);
        text_height=rect_radius/2+circle_radius+textRect.height()+rect_radius/2>(rect_radius/2+circle_radius)*2+rect_radius? textRect.height(): (rect_radius/2+circle_radius)+rect_radius ;
    }

    window_height=rect_radius/2+circle_radius+text_height+rect_radius/2>icon_height? rect_radius/2+circle_radius+text_height+rect_radius/2: icon_height;
    window_height=begin_height_spacing+triangle_height+window_height+begin_height_spacing;
}

效果

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章