1.界面效果
2.设计思路
用一个QListWidget来显示消息,一个QTextEdit来编辑消息,2个QPushButton代表2个正着聊天的小哥,点不同的按钮表示不同的人在发消息。
QListWidget添加消息时,实际添加的是一个自定义控件,这个也是核心所在。这个自定义控件要负责计算文字的高度和宽度,以及样式的渲染。我这里实现的自定义控件比较简单,由1个QWidget和1个QLabel构成,QLabel是QWidget的子控件,文本显示在QLabel上。
3.源码展示
ChatDialog.h
#pragma once
#include <QtWidgets/QMainWindow>
#include "ui_ChatDialog.h"
class ChatDialog : public QMainWindow
{
Q_OBJECT
public:
ChatDialog(QWidget *parent = Q_NULLPTR);
public slots:
void ZhangSanSay();
void LisiSay();
private:
Ui::ChatDialogClass ui;
};
ChatDialog.cpp
#include "ChatDialog.h"
#include "MsgWidget.h"
ChatDialog::ChatDialog(QWidget *parent)
: QMainWindow(parent)
{
ui.setupUi(this);
connect(ui.pushButton,SIGNAL(clicked()),this,SLOT(ZhangSanSay()));
connect(ui.pushButton_2, SIGNAL(clicked()), this, SLOT(LisiSay()));
}
//张三发消息
void ChatDialog::ZhangSanSay()
{
MsgWidget *widget = new MsgWidget(ui.listWidget->width(), ui.textEdit->toPlainText()
, MsgWidget::MSGWIDGET_LEFT, ui.listWidget);
QListWidgetItem *item = new QListWidgetItem();
ui.listWidget->addItem(item);
ui.listWidget->setItemWidget(item, widget);
item->setSizeHint(QSize(ui.listWidget->width(),widget->height()));
}
//李四发消息
void ChatDialog::LisiSay()
{
MsgWidget *widget = new MsgWidget(ui.listWidget->width(), ui.textEdit->toPlainText()
, MsgWidget::MSGWIDGET_RIGHT, ui.listWidget);
QListWidgetItem *item = new QListWidgetItem();
ui.listWidget->addItem(item);
ui.listWidget->setItemWidget(item, widget);
item->setSizeHint(QSize(ui.listWidget->width(), widget->height()));
}
MsgWidget.h
#pragma once
#include <QWidget>
class MsgWidget : public QWidget
{
Q_OBJECT
public:
//文本对齐方式:控制文本显示在聊天对话框的左边还是右边
enum MsgAlignment
{
MSGWIDGET_LEFT = 0,
MSGWIDGET_RIGHT = 1
};
public:
/*
int width:设置每条消息所占的宽度-其值应该为整个聊天记录显示区域的宽度
QString strTxt:消息文本
MsgAlignment alignment:对齐方式
QWidget *parent:父控件,可忽略
*/
MsgWidget(int width,QString strTxt, MsgAlignment alignment, QWidget *parent = NULL);
~MsgWidget();
private:
int m_iMaxWidthPerLine;
};
MsgWidget.cpp
#include "MsgWidget.h"
#include "QLabel"
MsgWidget::MsgWidget(int width,QString strTxt, MsgAlignment alignment, QWidget *parent)
: QWidget(parent)
{
m_iMaxWidthPerLine = 200;
//用QLable来显示文本
QLabel *pLabel = new QLabel(strTxt, this);
QFont myFont("楷体", 15);
pLabel->setFont(myFont);
pLabel->setWordWrap(true);
//计算要发送的消息显示到某个控件上时,此控件所需要的宽度和高度
QFontMetrics fm(myFont);
int textWidthInPixels = fm.width(strTxt);
int textHeightInPixels = fm.height() + 4;
int iLineNum = textWidthInPixels / m_iMaxWidthPerLine;
if (textWidthInPixels % m_iMaxWidthPerLine)
{
iLineNum += 1;
}
int iSetWidth = (textWidthInPixels > m_iMaxWidthPerLine) ?
m_iMaxWidthPerLine : textWidthInPixels;
iSetWidth += 4;//略微调整一下宽度,避免最边上的文字显示不全
int iSetHeight = iLineNum * textHeightInPixels;
//调整QLabel的大小和位置
if (MSGWIDGET_RIGHT == alignment)
{
pLabel->setGeometry(width - iSetWidth, 2, iSetWidth, iSetHeight);
pLabel->setStyleSheet("background-color:#73c1fd");
}
else
{
pLabel->setGeometry(0, 2, iSetWidth, iSetHeight);
pLabel->setStyleSheet("background-color:#c0cdd6");
}
//调整个消息界面的大小,这里主要调整了高度,不然连续发送多条消息时,各消息框之间没有空隙
this->setFixedSize(QSize(width, iSetHeight + 5));
}
MsgWidget::~MsgWidget()
{
}