qt聊天消息框显示

聊天消息框
公司最近需要使用qt开发一个局域网聊天工具,网上找了好多例子,也参考了好多文章,都不太理想,最后查到雨田哥写的使用QtWebEngine,实现了基本的功能,但是发送消息加换行也存在问题,自己也摸索了很长时间,现贴出代码,基本的效果有,但是展示还不太完美,做个引子吧,也咨询了一些大佬说要么自己封装控件,要么使用QWebView可能能满足需求,想了想还是应该使用QWebView比较简单吧,后面有时间了,自己实现下,欢迎大家做这方面的互相学习,共同分享交流:
效果图:
qt聊天消息框显示_第1张图片
代码:

#define MAINWINDOW_H

#include 
#include 
#include 
#include 
#include 

#include 
#include 
#include 

class QHBoxLayout;
class QVBoxLayout;


typedef struct Message
{
    QString name;               //消息发送者名称
    QString icon;              //消息发送者头像
    QString datetime;          //消息时间
    QString type;              //消息类型 image,file,message
    QString direct;             //消息方向 Send Receive
    QString message_id;         //消息id  {fdsfasdf-fewfewfe-ewfwe-fewf-fewfwefwef}
    QString content;            //消息内容   消息内容,文件全路径
    QString filename;           //文件名称
    QString filesize;           //文件大小
}Message;


class MessageFrame : public QFrame
{
    Q_OBJECT
public:
    explicit MessageFrame(Message msg, QWidget *parent = nullptr);
    ~MessageFrame()override;

private:
    void initUI();
    QHBoxLayout* m_mainLayout;
    Message m_pCurMessage;
    QTextEdit* m_messageEdit;

private slots:
    void adjustContent();
};


class ChatFrame : public QScrollArea
{
    Q_OBJECT

public:
    explicit ChatFrame(QWidget* parent = nullptr);
    ~ChatFrame()override;

    //添加消息
    void addMessage(Message msg);

private:
    QVBoxLayout* m_vLayout;
    QScrollBar* m_verticalBar;
    QLabel *m_pHistoryLabel;

    QList m_pMessages;
};

class MainWindow : public QMainWindow
{
    Q_OBJECT
public:
    explicit MainWindow(QWidget *parent = nullptr);
    ~MainWindow()override;

protected:
    bool eventFilter(QObject *object, QEvent *event)override;

private:

    QWidget *m_mainWidget;
    ChatFrame*   m_chatWidget;
    QTextEdit *m_sendTextEdit;
    QVBoxLayout *m_vBoxLayout;

    void initUI();
    void sendMessage();

};
#endif // MAINWINDOW_H

```cpp
#include "mainwindow.h"

#include 
#include 
#include 
#include 
#include 
#include 

MessageFrame::MessageFrame(Message msg, QWidget* parent)
    : QFrame (parent)
{
    m_mainLayout = new QHBoxLayout;
    m_pCurMessage = msg;
    initUI();
    setLayout(m_mainLayout);
    m_mainLayout->setContentsMargins(0,0,0,0);
    setFrameShape(QFrame::NoFrame);
    this->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Preferred);
}

MessageFrame::~MessageFrame()
{

}

void MessageFrame::initUI()
{
    QVBoxLayout* play = new QVBoxLayout;
    m_messageEdit = new QTextEdit;
    connect(m_messageEdit->document(),&QTextDocument::contentsChange,this,&MessageFrame::adjustContent);
    m_messageEdit->setMaximumWidth(300);
    m_messageEdit->setText(m_pCurMessage.content);
    m_messageEdit->setTextColor(Qt::white);
    m_messageEdit->setReadOnly(true);
    m_messageEdit->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
    m_messageEdit->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
    m_messageEdit->setStyleSheet("background-color:rgba(0,129,255,1); color:white;border-radius:5px;");
    m_messageEdit->viewport()->setContentsMargins(20,0,20,0);
    m_messageEdit->setMouseTracking(true);
    m_messageEdit->viewport()->setMouseTracking(true);
    m_messageEdit->viewport()->installEventFilter(this);
    m_messageEdit->setAlignment(Qt::AlignLeft);
    QHBoxLayout* pl = new QHBoxLayout;
    pl->addStretch(10);
    pl->addWidget(m_messageEdit);
    play->addLayout(pl);
    play->setSpacing(10);
    m_mainLayout->addLayout(play);
}

void MessageFrame::adjustContent()
{
    QTextDocument *document=qobject_cast(sender());
    document->adjustSize();
    if(document)
    {
        document->setDocumentMargin(8);
        QTextEdit *editor = qobject_cast(document->parent()->parent());
        if (editor) {
            QString text = editor->toPlainText().trimmed();
            if (text.isEmpty()) {
               return;
            }
            QFontMetrics mert  = editor->viewport()->fontMetrics();
            int nCount = text.count("\n");
            int width = mert.width(text);
            int height = mert.height();

            if (width > editor->maximumWidth() || (width < editor->maximumWidth() && nCount > 0)) {
                float fheight = (width / (300*1.0)) + nCount;
                int nheight = (width / (300*1.0)) + nCount;
                float d = fheight - nheight;
                if (fheight - nheight > 0 ) {
                    nheight ++;
                }
                if (d < 0.5) {
                    editor->setFixedSize(300, nheight * height + 28 );
                } else {
                    editor->setFixedSize(300, nheight * height + 30 );
                }
            } else
            {
                editor->setFixedSize(width + 28, 36);
            }
        }
    }
}

ChatFrame::ChatFrame(QWidget* parent)
    : QScrollArea(parent)
{
    QWidget* pWidget = new QWidget(this);

    m_vLayout = new QVBoxLayout;

    m_vLayout->setSpacing(10);

    m_vLayout->setContentsMargins(20,20,20,20);

    m_vLayout->addStretch(10);

    pWidget->setLayout(m_vLayout);

    this->setWidgetResizable(true);

    this->setVerticalScrollBarPolicy(Qt::ScrollBarAsNeeded);

    m_verticalBar = new QScrollBar;

    this->setVerticalScrollBar(m_verticalBar);

    this->setSizeAdjustPolicy(QAbstractScrollArea::AdjustToContents);

    this->setWidget(pWidget);
}

ChatFrame::~ChatFrame()
{

}

void ChatFrame::addMessage(Message msg)
{
    MessageFrame* pFrame = new MessageFrame(msg, this->widget());

    int count = m_vLayout->count();
    m_vLayout->insertWidget(count-1, pFrame);
    m_verticalBar->setRange(0, this->widget()->height());
    //所有消息列表
    m_pMessages.push_back(pFrame);

    m_verticalBar->setValue(m_verticalBar->maximum());
}

MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent)
{
    initUI();
}

void MainWindow::initUI()
{

    m_mainWidget = new QWidget;
    m_vBoxLayout = new QVBoxLayout;

    m_chatWidget = new ChatFrame(this);
    m_chatWidget->setFrameShape(QFrame::NoFrame);

    m_sendTextEdit = new QTextEdit;
    m_sendTextEdit->setPlaceholderText(tr("Welcome to contact us, please describe your questions"));
    m_sendTextEdit->installEventFilter(this);

    m_vBoxLayout->addWidget(m_chatWidget);
    m_vBoxLayout->addWidget(m_sendTextEdit);
    m_vBoxLayout->setStretchFactor(m_chatWidget, 10);
    m_vBoxLayout->setStretchFactor(m_sendTextEdit, 2);
    m_mainWidget->setLayout(m_vBoxLayout);
    setCentralWidget(m_mainWidget);
}

MainWindow::~MainWindow()
{

}

bool MainWindow::eventFilter(QObject *object, QEvent *event)
{
    if(object == m_sendTextEdit)
    {
         if(event->type() == QEvent::KeyPress)
         {
             QKeyEvent* peve = dynamic_cast(event);
             if((peve->modifiers() & Qt::ControlModifier) && (peve->key() == Qt::Key_Return || peve->key() == Qt::Key_Enter)) //Ctrl + Enter 换行
             {
                 m_sendTextEdit->insertPlainText(QString(" ") += '\n');
                 return true;
             }
             if(peve->key() == Qt::Key_Return || peve->key() == Qt::Key_Enter) //回车键盘
             {
                 sendMessage();
                 return true;
             }
         }
    }
    return QMainWindow::eventFilter(object, event);
}

void MainWindow::sendMessage()
{
    QString msg = m_sendTextEdit->toPlainText();

    // 把最后一个回车换行符删掉
    while (msg.endsWith("\n")) {
        msg.remove(msg.length() - 2, 2);
    }
    if(msg.isEmpty())
    {
        QMessageBox msgBox;
        msgBox.setText("cannot input empty message");
        msgBox.exec();
        return;
    }
    // 清除输入框
    m_sendTextEdit->clear();
    Message message;
    message.content = msg;
    m_chatWidget->addMessage(message);
}

```cpp
#include "mainwindow.h"

#include 

int main(int argc, char *argv[])
{
   QApplication a(argc, argv);

    MainWindow w;
    w.resize(500, 500);
    w.show();

    return a.exec();
}


你可能感兴趣的:(qt)