一、消息展示区
消息展示区需要再MessageShowArea文件里编写代码
目前只完成了文本消息:
MessageShowArea.h文件
#include <QScrollArea>
#include <QWidget>
#include <QLabel>
#include <QPushButton>
#include "model/data.h"
#include "debug.h"
// .h 文件中不宜进行 using namespace xxxx
using model::Message;
////////////////////////////////////////////////////////
/// 消息展示区
////////////////////////////////////////////////////////
class MessageShowArea : public QScrollArea
{
Q_OBJECT
public:
MessageShowArea();
// 尾插
void addMessage(bool isLeft, const Message& message);
// 头插
void addFrontMessage(bool isLeft, const Message& message);
// 清空消息
void clear();
// 滚动到末尾
void scrollToEnd();
private:
QWidget* container;
};
////////////////////////////////////////////////////////
/// 表示一个消息元素
/// 这个里面要能同时支持 文本消息, 图片消息, 文件消息, 语音消息.
/// 当前先只考虑文本消息. 另外几个后续慢慢添加.
////////////////////////////////////////////////////////
class MessageItem : public QWidget {
Q_OBJECT
public:
// 此处的 isLeft 表示这个 Item 是否是一个 "左侧消息"
MessageItem(bool isLeft);
// 通过 工厂方法 创建 MessageItem 实例
static MessageItem* makeMessageItem(bool isLeft, const Message& message);
// 添加工厂函数
static QWidget* makeTextMessageItem(bool isLeft, const QString& message);
static QWidget* makeImageMessageItem();
static QWidget* makeFileMessageItem();
static QWidget* makeSpeechMessageItem();
private:
bool isLeft;
};
////////////////////////////////////////////////////////
/// 创建类表示 "文本消息" 正文部分
////////////////////////////////////////////////////////
class MessageContentLabel : public QWidget {
public:
// fileName 可以作为 text 的一部分, 传递进来. 不需要单独列一个参数
MessageContentLabel(const QString& text, bool isLeft);
void paintEvent(QPaintEvent* event) override;
private:
QLabel* label;
bool isLeft;
model::MessageType messageType;
QString fileId;
QByteArray content;
bool loadContentDone = false;
};
MessageShowArea.cpp文件
#include <QScrollBar>
#include <QVBoxLayout>
#include <QPushButton>
#include <QLabel>
#include <QFontMetrics>
#include <QPainter>
#include <QPainterPath>
#include <QFileDialog>
#include <QTimer>
#include <QMenu>
MessageShowArea::MessageShowArea() {
// 1. 初始化基本属性
this->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
this->setWidgetResizable(true);
// 设置滚动条的样式
this->verticalScrollBar()->setStyleSheet("QScrollBar:vertical { width: 2px; background-color: rgb(240, 240, 240); }");
this->horizontalScrollBar()->setStyleSheet("QScrollBar:horizontal { height: 0;}");
this->setStyleSheet("QScrollArea { border: none; }");
// 2. 创建 Container 这样的 widget, 作为包含内部元素的容器
container = new QWidget();
this->setWidget(container);
// 3. 给 container 添加布局管理器
QVBoxLayout* layout = new QVBoxLayout();
layout->setSpacing(0);
layout->setContentsMargins(0, 0, 0, 0);
container->setLayout(layout);
// 添加 "构造测试数据" 逻辑.
#if TEST_UI
for (int i = 1; i <= 30; ++i) {
model::UserInfo userInfo;
userInfo.userId = QString::number(1000 + i);
userInfo.nickname = "张三" + QString::number(i);
userInfo.description = "从今天开始认真敲代码";
userInfo.avatar = QIcon(":/resource/image/defaultAvatar.png");
userInfo.phone = "18612345678";
Message message = Message::makeMessage(model::TEXT_TYPE, "", userInfo, (QString("这是一条测试消息") + QString::number(i)).toUtf8(), "");
this->addMessage(true, message);
}
#endif
}
void MessageShowArea::addMessage(bool isLeft, const Message &message)
{
// 构造 MessageItem, 添加到布局管理器中.
MessageItem* messageItem = MessageItem::makeMessageItem(isLeft, message);
container->layout()->addWidget(messageItem);
}
void MessageShowArea::addFrontMessage(bool isLeft, const Message &message)
{
MessageItem* messageItem = MessageItem::makeMessageItem(isLeft, message);
QVBoxLayout* layout = dynamic_cast<QVBoxLayout*>(container->layout());
layout->insertWidget(0, messageItem);
}
void MessageShowArea::clear()
{
// 遍历布局管理器, 删除里面的元素
QLayout* layout = container->layout();
for (int i = layout->count() - 1; i >= 0; --i) {
QLayoutItem* item = layout->takeAt(i);
if (item != nullptr && item->widget() != nullptr) {
delete item->widget();
}
}
}
void MessageShowArea::scrollToEnd()
{
// 实现思路:
// 拿到滚动区域中的滚动条(垂直滚动条)
// 获取到滚动条的最大值
// 根据最大值, 设置滚动条的滚动位置.
// 为了使滚动效果更佳, 能够在界面绘制好之后进行滚动条的设置
// 给这里的滚动操作, 加上个 "延时"
QTimer* timer = new QTimer();
connect(timer, &QTimer::timeout, this, [=]() {
// 获取到垂直滚动条的最大值
int maxValue = this->verticalScrollBar()->maximum();
// 设置滚动条的滚动位置
this->verticalScrollBar()->setValue(maxValue);
timer->stop();
timer->deleteLater();
});
timer->start(500);
}
///////////////////////////////////////////////////////
/// 表示一个消息元素
////////////////////////////////////////////////////////
MessageItem::MessageItem(bool isLeft)
:isLeft(isLeft)
{
}
MessageItem *MessageItem::makeMessageItem(bool isLeft, const Message &message)
{
// 1. 创建对象和布局管理器
MessageItem*

最低0.47元/天 解锁文章
1852

被折叠的 条评论
为什么被折叠?



