项目实战:仿QQ的QQ简洁版2019群聊项目

简介: 自我熟练qtwidget的使用,熟悉使用qtnetwork相关模块写一个仿QQQQ简洁版2019群聊项目。哇伊,这是我大学之处一直想写的IM即时通讯系统的,模仿写一个QQ的项目,但是因为时间等关系,断断续续的只是写了一些IM_QQ的部分相关功能的知识,每回写一个核心功能,但到了现在这会,感觉基本几大核心功能(登录,单人聊天,群聊功能,数据库设计)已经写好了,后续有时间,就将其完整的写成一个完整版的QQ

本博文的简述or解决问题?

​ 自我熟练qtwidget的使用,熟悉使用qtnetwork相关模块写一个仿QQQQ简洁版2019群聊项目。哇伊,这是我大学之处一直想写的IM即时通讯系统的,模仿写一个QQ的项目,但是因为时间等关系,断断续续的只是写了一些IM_QQ的部分相关功能的知识,每回写一个核心功能,但到了现在这会,感觉基本几大核心功能(登录,单人聊天,群聊功能,数据库设计)已经写好了,后续有时间,就将其完整的写成一个完整版的QQ


开发环境:

编程环境: win10 x64 专业版

编程软件: Qt Creator 4.8.2 (Enterprise)Qt 5.9.7


项目简介:

使用qt实现QQ的核心功能之一:群聊功能。

功能实现:

  • 群聊功能

  • 群成员上线,下线会有自动提示

  • 群成员在线动态列表

  • 联系人好友列表

  • 聊天记录保存到*.txt文本文件

  • 清空聊天界面

  • 聊天字体的变化:字体、字号、颜色、加粗、倾斜、下划线


项目特色:

写这个,不仅仅是一个单独的小功能,而是在学习的前进的路上,逐步完善核心功能,最后独立写一个完整版的即时通讯IM,准备以QQ为参考。若是以后写出来了,是会发表称为系列博客,供大家开源学习与交流的

仿QQ项目的IM即时通讯,已经实现的相关的功能:


任重而道远,后续还有服务器的高并发等学习,为我的IM奠定基础,不慌不躁,心虽急,但是干活不可急,始终坚信:


慢而不出差错,就是快


运行效果:


视频演示效果:

https://www.bilibili.com/video/av59692500 (csdn貌似不支持插入bilibili视频,反正设置了无效),文末同步博文链接可以查看效果


图片演示效果:

  • 联系人列表:

  • 群聊界面:


设计思路:

  • 输入准备发送的消息到控件
  • 槽函数获获取控件消息,转换换成QString存储
  • 使用qtnetwork模块,用QUdpSocket发送广播,构建群聊功能
  • 对于感兴趣的消息截取,
  • 解析协议,获取发送的数据报的内容
  • 再次在其它的控件显示出来
  • 时刻更新显示

部分源码:

核心的群聊功能实现如下:

#include "DlgGroupChat.h"
#include "ui_DlgGroupChat.h"
#include <QByteArray>
#include <QDataStream>
#include <QMessageBox>
#include <QDateTime>
#include <QDebug>
#include <QColorDialog>
#include <QFileDialog>

DlgGroupChat::DlgGroupChat(QWidget *parent, QString name) :
    QWidget(parent),
    ui(new Ui::DlgGroupChat)
{
    ui->setupUi(this);

    //初始化
    m_pUdpSocket = new QUdpSocket;
    m_strUserName = name;
    m_nPort = 9999;
    m_pUdpSocket->bind(this->m_nPort, QAbstractSocket::ShareAddress | QAbstractSocket::ReuseAddressHint);  //共享地址+断开重连

    connect(ui->pbSend, &QPushButton::clicked, [=](){
        sendMsg(UserMsg);
    });

    sendMsg(UserEnter);

    connect(m_pUdpSocket, &QUdpSocket::readyRead, this, &DlgGroupChat::recvMsg);

    //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
    //字体
    connect(ui->fcbFont, &QFontComboBox::currentFontChanged, [=](const QFont &font){
       ui->teChatInput->setCurrentFont(font);
       ui->teChatInput->setFocus();
    });

    //字号
    void (QComboBox:: *cbxsingal)(const QString &text) = &QComboBox::currentIndexChanged;
    connect(ui->comboBox, cbxsingal, [=](const QString &text){
       ui->teChatInput->setFontPointSize(text.toDouble());
       ui->teChatInput->setFocus();
    });

    //加粗
    connect(ui->tbFontBold, &QToolButton::clicked, [=](bool isCheck){
        if(isCheck)
            ui->teChatInput->setFontWeight(QFont::Bold);
        else
            ui->teChatInput->setFontWeight(QFont::Normal);

        ui->teChatInput->setFocus();
    });

    //倾斜
    connect(ui->tbFontTilt, &QToolButton::clicked, [=](bool Check){
        ui->teChatInput->setFontItalic(Check);
        ui->teChatInput->setFocus();
    });

    //下划线
    connect(ui->tbFontUnderline, &QToolButton::clicked, [=](bool Check){
        ui->teChatInput->setFontUnderline(Check);
        ui->teChatInput->setFocus();
    });

    //字体颜色
    connect(ui->tbMark, &QToolButton::clicked, [=](){
        QColor color = QColorDialog::getColor(Qt::red);
        ui->teChatInput->setTextColor(color);
        ui->teChatInput->setFocus();
    });

    //保存聊天记录
    connect(ui->tbChatSave, &QToolButton::clicked, [=](){
        QString path = QFileDialog::getSaveFileName(this, "保存记录", "聊天记录", "(*.txt)");
        if(path.isEmpty()  || ui->tbChat->document()->isEmpty())
        {
            QMessageBox::warning(this, "警告", "路径或者内容不能为空");
            return;
        }
        else
        {
            QFile file(path);
            file.open(QIODevice::WriteOnly | QIODevice::Text);
            QTextStream stream(&file);
            stream << ui->tbChat->toPlainText();
            file.close();
        }

        ui->teChatInput->clear();
        ui->teChatInput->setFocus();
    });

    //清空聊天记录
    connect(ui->tbChatClean, &QToolButton::clicked, [=](){
        ui->tbChat->clear();
        ui->teChatInput->setFocus();
    });





}

DlgGroupChat::~DlgGroupChat()
{
    delete ui;
}



void DlgGroupChat::closeEvent(QCloseEvent* e)
{
    emit this->closeDlgGroupChat();

    sendMsg(UserLeft);
    close();
}

void DlgGroupChat::sendMsg(DlgGroupChat::MsgType typeMsg)
{
    QByteArray array;
    QDataStream stream(&array,QIODevice::WriteOnly);

    stream << typeMsg;  //将类型加入到 流中

    switch (typeMsg)
    {
    case UserMsg:{
        if(ui->teChatInput->toPlainText().isEmpty())
        {
            QMessageBox::warning(this, "警告", "发送的消息不能为空");
            return;
        }

        //报文协1:类型+姓名+时间+内容
        QString time = QDateTime::currentDateTime().toString("yyyy-mm-dd hh:mm:ss");
        QString msg = ui->teChatInput->toHtml();
        stream <<m_strUserName<<time<< msg;

        ui->teChatInput->clear();
        ui->teChatInput->setFocus();

    }break;
    case UserEnter:{
        //报文协议2:类型+姓名
        stream <<m_strUserName;
    }break;
    case UserLeft:{
        //报文协议3:类型+姓名
        stream <<m_strUserName;
    }break;
    default:
        break;
    }

    //书写报文,广播发送
    m_pUdpSocket->writeDatagram(array, QHostAddress::Broadcast, m_nPort);

}

void DlgGroupChat::userEnter(QString userName)
{
    bool isEmpty = ui->twUser->findItems(userName, Qt::MatchExactly).isEmpty();

    if(isEmpty)   //不存在才能添加显示
    {
        QTableWidgetItem* item = new QTableWidgetItem(userName);
        QString time = QDateTime::currentDateTime().toString("yyyy-MM-dd hh:mm:ss");
        QTableWidgetItem* timeItem = new QTableWidgetItem(time);

        //插入行
        ui->twUser->insertRow(0);
        ui->twUser->setItem(0, 0, item);
        ui->twUser->setItem(0, 1, timeItem);

        //追加聊天记录
        ui->tbChat->setTextColor(Qt::gray);
        ui->tbChat->append(QString("%1 于 %2 上线了").arg(userName).arg(time));

        //在线人数更新
        ui->labCount->setText(QString("在线用户:%1人").arg(ui->twUser->rowCount()));
        sendMsg(UserEnter);

    }


}

void DlgGroupChat::userLeft(QString userName)
{
    bool isEmpty = ui->twUser->findItems(userName, Qt::MatchExactly).isEmpty();

    if(!isEmpty) //存在才能离开显示
    {
        int nRow = ui->twUser->findItems(userName, Qt::MatchExactly).first()->row();
        ui->twUser->removeRow(nRow);
        QString time = QDateTime::currentDateTime().toString("yyyy-mm-dd hh:mm:ss");

        //追加聊天记录
        ui->tbChat->setTextColor(Qt::gray);
        ui->tbChat->append(QString("%1 于 %2 下线了").arg(userName).arg(time));

        //在线人数更新
        ui->labCount->setText(QString("在线用户:%1人").arg(ui->twUser->rowCount()));
    }
}



void DlgGroupChat::recvMsg()
{
    qint64 size = m_pUdpSocket->pendingDatagramSize();  //获取接收报文的长度
    QByteArray array = QByteArray(size, 0);
    m_pUdpSocket->readDatagram(array.data(), size);

    //解析报文协议:类型+姓名+时间+内容

    QString name;
    QString time;
    int typeMsg;
    QString Msg;
    QDataStream stream(&array, QIODevice::ReadOnly);
    stream >> typeMsg >> name  >> time >> Msg;

    qDebug()<<size<<" recv=>"<<QString::fromLocal8Bit(array);

    switch (typeMsg)
    {
    case UserMsg:{
        ui->tbChat->setTextColor(Qt::blue);
        ui->tbChat->append("[" + name +"]" + time);
        ui->tbChat->append(Msg);
    }break;
    case UserEnter:{
        userEnter(name);

    }break;
    case UserLeft:{
        userLeft(name);
    }break;
    default:
        break;
    }

}

void DlgGroupChat::on_pbExit_clicked()
{
    sendMsg(UserLeft);
    close();
}


源码下载:

源码:IM_QQ 感兴趣的话 欢迎 star 和 fork 这个项目,给它提交贡献,进行合并


相关资源:

提供一些QQ的文源文件共享:[QQ界面资源分享]

Chat_IM_QQ

QQemoji小表情:



QQ登录界面图片:


QQ各种钻vip图标:


QQ群聊界面:



系列地址:

QtExamples

欢迎 starfork 这个系列的 QT / DTK 学习,附学习由浅入深的目录。

  • 6
    点赞
  • 32
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 5
    评论
### 回答1: Qt是一个跨平台的应用程序开发框架,支持多种操作系统,如Windows、Linux、macOS等。在Qt中可以很方便的实现网络通信、图像处理等功能,因此非常适合用于开发仿QQ、微信等通信软件。下面我们来探讨一下如何用Qt实现仿QQ、微信截图的功能。 首先,需要了解Qt中的图像处理类QImage和QPainter。QImage类能够对图像进行处理、读取和保存,而QPainter类则能够在QImage上进行绘图。使用这两个类可以实现截图功能。具体步骤如下: 1. 获取屏幕上要截图区域的位置和大小。 2. 创建与屏幕截图区域大小相同的QImage对象,将截图区域中的像素信息读取到QImage对象中。 3. 创建QPixmap对象,将QImage对象转换为QPixmap对象,显示在截图窗口中。 4. 可以用鼠标在QPixmap对象上选择要截取的区域。 5. 将选择的区域转换为QImage对象,保存为本地文件或者上传到服务器。 以上就是用Qt实现仿QQ、微信截图的基本步骤。需要注意的是,需要在Qt的UI界面上添加相关按钮和事件处理函数,使得用户可以完成截图、保存、上传等操作。此外,为了保证截图区域选取的精度和准确性,还需要对鼠标事件进行处理。 总的来说,Qt是一款功能强大的开发框架,它提供了许多图形界面和图像处理类,使得开发者可以快速地开发出各种应用程序,包括仿QQ、微信截图工具。希望开发者能够熟练掌握Qt的相关知识和技能,为用户提供更好的软件体验。 ### 回答2: Qt是一个跨平台的应用程序开发框架,可用于开发多种类型的应用程序,包括桌面应用程序和移动应用程序。本项目旨在使用Qt框架开发一个仿QQ微信截图的应用程序。 该应用程序主要包括两个部分:界面和功能。界面部分将仿QQ和微信的截图界面,包括截屏、编辑、保存等功能功能部分主要包括截屏、编辑、保存、撤销、恢复、裁剪、缩放、滤镜等功能。 在开发过程中,应先选择一个合适的界面布局,以便开发者更好地组织整个应用程序。可以选择常见的水平布局或垂直布局,也可以选择网格布局以适应不同的屏幕大小。 接下来,将添加应用程序的主要功能。首先是截屏功能,可以通过PC屏幕截取用户想要的部分。然后,用户可以对其进行编辑,例如绘制、添加文本、调整大小等。编辑完成后,应用程序将保存所做的更改,并提供撤销和恢复命令以便撤销和反撤销所做的更改。 应用程序还可以实现裁剪、缩放和滤镜等功能。这些功能可根据用户需求来添加或删除。 最后,应用程序应该能够保存编辑后的截图。根据用户要求,可以将截图保存到本地或上传到云端服务。此外,还可以将截图分享到社交平台,以便用户分享自己的精彩瞬间。 总之,Qt框架提供了各种工具和库,使得开发者可以开发高级的桌面应用程序。作为一个仿QQ微信截图的应用程序,开发者可以根据自己的需要添加或删除功能,以实现自己的设计目标。
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

偕臧x

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值