Qt编写自定义控件:聊天记录展示控件

这篇博客展示了如何利用Qt的QPainter类来实现一个简单的聊天对话界面。代码中定义了聊天信息结构体,并创建了一个聊天对话框类,包含了头像列表、用户名和聊天记录。在paintEvent函数中,根据聊天信息的用户名绘制了不同位置的头像和聊天内容,实现了对话气泡的布局。博客探讨了QPainter的使用技巧,包括文本绘制、头像绘制和自定义气泡形状。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

代码:

#include <QWidget>
#include <QMap>

struct chatInfo//聊天信息
{
    chatInfo(QString chatString,QString userName)
        : chatString(chatString),
          userName(userName)
    {
    }
    QString chatString;
    QString userName;
};

class chatDialog : public QWidget
{
    Q_OBJECT

public:
    chatDialog(QWidget *parent = nullptr);
    ~chatDialog();
protected:
    void paintEvent(QPaintEvent *event)override;
private:
    QMap<QString,QPixmap> headPicMap;//头像列表
    QString userName{"张三"};
    QList<chatInfo> chatList;
};
#include "chatdialog.h"
#include <QPaintEvent>
#include <QPainter>
#include <QPainterPath>

chatDialog::chatDialog(QWidget *parent)
    : QWidget(parent)
{
    headPicMap.insert(this->userName,QPixmap(":/img01.png"));
    headPicMap.insert("李四",QPixmap(":/img02.png"));

    chatList << chatInfo("你好呀",this->userName);
    chatList << chatInfo("你好","李四");
    chatList << chatInfo("今天天气不错",this->userName);
    chatList << chatInfo("明镜高堂悲白发,朝如青丝暮成雪",this->userName);
    chatList << chatInfo("是呀","李四");
    chatList << chatInfo("黄河之水天上来,奔流到海不复回","李四");

    setMinimumWidth(300);
}

chatDialog::~chatDialog()
{
}

void chatDialog::paintEvent(QPaintEvent *event)
{
    auto rect = event->rect();
    const auto width = rect.width();
    QPainter painter(this);
    painter.setRenderHint(QPainter::Antialiasing);
    painter.setRenderHint(QPainter::SmoothPixmapTransform);

    QFont font;
    font.setPixelSize(24);
    painter.setFont(font);
    painter.fillRect(rect,QColor("#F5F5F5"));
    int nowDrawHeight = 10;//绘制高度
    for (int i = 0;i < chatList.size();++i)
    {
        auto & chatInfomation = chatList.at(i);
        if(chatInfomation.userName == this->userName)//自己的
        {
            painter.drawPixmap(QRect(width - 42,nowDrawHeight,32,32),headPicMap[chatInfomation.userName]);//绘制自己的头像
            QRectF textRect = painter.boundingRect(QRectF(width * 0.4,nowDrawHeight,width * 0.6 - 42 - 30,30),Qt::AlignRight | Qt::AlignVCenter | Qt::TextWordWrap,chatInfomation.chatString);

            if(textRect.topLeft().y()  < nowDrawHeight)
                textRect.moveTopLeft(QPointF(textRect.topLeft().x(),nowDrawHeight));

            QPainterPath path;
            auto areaRect = textRect.adjusted(-3,-3,3,3);
            path.addRoundedRect(areaRect,6,6);
            QPolygonF polygon;
            auto point1 = areaRect.topRight() + QPointF(0,6);
            polygon.append(point1);
            polygon.append(point1 + QPointF(20,8));
            polygon.append(point1 + QPointF(0,18));
            path.addPolygon(polygon);
            painter.fillPath(path,QColor("#2EC100"));

            painter.setPen(QColor("#2f2f2f"));
            painter.drawText(textRect,chatInfomation.chatString);

            nowDrawHeight = textRect.bottomRight().y() + 20;
        }
        else
        {
            painter.drawPixmap(QRect(10,nowDrawHeight,32,32),headPicMap[chatInfomation.userName]);
            QRectF textRect = painter.boundingRect(QRectF(72,nowDrawHeight,width * 0.6 - 72,30),Qt::AlignLeft | Qt::AlignVCenter | Qt::TextWordWrap,chatInfomation.chatString);

            if(textRect.topLeft().y()  < nowDrawHeight)
                textRect.moveTopLeft(QPointF(textRect.topLeft().x(),nowDrawHeight));

            QPainterPath path;
            auto areaRect = textRect.adjusted(-3,-3,3,3);
            path.addRoundedRect(areaRect,6,6);

            QPolygonF polygon;
            auto point1 = areaRect.topLeft() + QPointF(0,6);
            polygon.append(point1);
            polygon.append(point1 - QPointF(20,-8));
            polygon.append(point1 + QPointF(0,18));
            path.addPolygon(polygon);

            painter.fillPath(path,Qt::white);

            painter.setPen(QColor("#2f2f2f"));

            painter.drawText(textRect,chatInfomation.chatString);
            nowDrawHeight = textRect.bottomRight().y() + 20;
        }
    }

    QWidget::paintEvent(event);
}

效果:

 

心中有坐标,万物皆可绘。欧耶。

 

相关博文:QPainter详解

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值