Qt聊天室项目

该文章详细介绍了使用Qt构建聊天室应用的过程,包括用户注册、登录、好友列表、好友对话等功能的实现。项目使用了单例模式管理套接字,通过JSON串进行数据传输,同时利用信号槽机制处理用户交互和服务器通信。数据库用于存储用户信息,服务器端使用多线程处理客户端连接,并实现了用户上线、下线的通知功能。

Qt聊天室项目

一,主要功能

整体代码

注册

  • 输入用户ID与账号密码,注册成功返回账号
  • 注册结束后返回登录界面

登录

  • 用户可以选择直接登录或者注册账号
  • 登录失败提示账号密码错误
  • 登录成功进入好友列表界面

好友列表

  • 显示已经登录的好友
  • 如果有好友发送新的消息,进行提示

好友对话

  • 发送和接收消息并显示在对话框中

服务器

  • 实现多线程并发服务器

二,注册功能实现

2.1 UI界面

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-w0ZNOPrF-1687012526102)(C:\Users\28558\AppData\Roaming\Typora\typora-user-images\image-20230617091508231.png)]

2.2 工作流程

1.进入页面(构建对象)
  • 获取通讯用套接字->[单例模式](# 七,单例模式)
socket = MySocket::getIns();
  • 通过连接函数connect()监听readyRead()信号
	//接收数据的连接函数 套接字发送readyRead信号
	connect(socket,SIGNAL(readyRead()),this,SLOT(slot_read()));
2.输入昵称与密码
    //获取文本内容
    QString nickname = ui->lineEdit_nickname->text();
    QString pass = ui->lineEdit_pass->text();
3.点击注册按钮->信号与槽
  • 向服务器发送消息->json串
/*注册按钮的槽函数,作用是将昵称和密码中的文本构建出字符型发送给服务器*/
void RegistDialog::on_pushButton_regist_clicked()
{
   
   
    //获取文本内容
    QString nickname = ui->lineEdit_nickname->text();
    QString pass = ui->lineEdit_pass->text();
    //构建json串
    QString jsonstr = MsgBuilder::buildRegisterUserMsg(pass,0,nickname);
    //发送内容给服务器 QString->QByteArray
    socket->write(jsonstr.toLocal8Bit());
}
/*readyRead()信号的槽函数,当服务器发送消息的时候调用,作用为解析返回的json串,并显示返回的id(账号)*/
void RegistDialog::slot_read()
{
   
   
    //获取接收信息
    QByteArray data = socket->readAll();
    //QByteArray->QString
    QString jsonStr = QString::fromLocal8Bit(data);
    qDebug()<<jsonStr;
    //解析json
    int id = MsgBuilder::parseRegisterUserReturnMsg(jsonStr);
    //显示在画面上
    ui->label_id->setNum(id);
}
4.点击退出,返回登录界面
/*退出界面时,断开本界面对socket中readyRead()信号的监听*/
void RegistDialog::closeEvent(QCloseEvent *)
{
   
   
    //断开连接函数
    disconnect(socket,SIGNAL(readyRead()),this,SLOT(slot_read()));
}

三,登录功能实现

3.1 UI界面

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-g83u1rZM-1687012526104)(C:\Users\28558\AppData\Roaming\Typora\typora-user-images\image-20230617103401937.png)]

3.2 工作流程

1.进入界面
  • 获取通讯套接字
  • 通过连接函数connect()监听connected()信号
//连接服务器成功套接字会发送connected信号
    connect(socket,SIGNAL(connected()),this,SLOT(slot_con()));
  • 通过连接函数connect()监听readyRead()信号
    //接收数据 套接字会发送readyRead信号
    connect(socket,SIGNAL(readyRead()),this,SLOT(slot_read()));
2. 点击connect按钮
/*connect按钮的槽函数,负责与服务器进行连接,连接成功后服务器会返回connected信号*/
void LoginDialog::on_pushButton_connect_clicked()
{
   
   
    //获取文本内容
    QString ip = ui->lineEdit_ip->text();
    //连接服务器
    socket->connectToHost(QHostAddress(ip),12345);
}
/*服务器返回连接信号调用对应槽函数,将界面的按钮恢复活性*/
void LoginDialog::slot_con()
{
   
   
    qDebug()<<"连接成功";
    //把失活的按钮变成活性
    ui->lineEdit_id->setEnabled(true);
    ui->lineEdit_pass->setEnabled(true);
    ui->pushButton_login->setEnabled(true);
    ui->pushButton_regist->setEnabled(true);
}
3.点击注册按钮
/*点击注册按钮弹出注册界面,此时登录界面断开对readyread()信号的监听*/
void LoginDialog::on_pushButton_regist_clicked()
{
   
   
    //页面切换
    RegistDialog *r = new RegistDialog(this);
    //断开连接函数  断开哪个信号 断开哪个槽函数
    disconnect(socket,SIGNAL(readyRead()),this,SLOT(slot_read()));
    //显示页面 (带有阻塞效果)
    r->exec();
    //连接函数
    connect(socket,SIGNAL(readyRead()),this,SLOT(slot_read()));
}
4.点击登录按钮
/*登录按钮的槽函数,负责将先前输入的id与密码发送给服务器*/
void LoginDialog::on_pushButton_login_clicked()
{
   
   
    //获取文本内容
    QString id = ui->lineEdit_id->text();
    QString pass = ui->lineEdit_pass->text();
    //构建json
    QString jsonstr = MsgBuilder::buildLoginMsg(id.toInt(), pass);
    qDebug()<<jsonstr;
    //发送给服务器
    socket->write(jsonstr.toLocal8Bit());
}
/*服务器返回readyread信号,对应的槽函数slot_read根据返回的消息类型进行处理*/
void LoginDialog::slot_read()
{
   
   
    //获取接收数据
    QByteArray data = socket->readAll();
    //QByteArray->QString
    QString jsonstr = QString::fromLocal8Bit(data);
    qDebug()<<jsonstr;
    //获取消息类型
    int type = MsgBuilder::msgType(jsonstr);
    //判断消息类型
    switch (type) {
   
   
    case MsgBuilder::loginSucReturn://登录成功 type =3
        deelUserLoginSuc(jsonstr);//处理登录成功函数
        break;
    case MsgBuilder::loginLoseReturn://登录失败 type =4
        QMessageBox::information(this,"提示","登陆失败!请确认账号和密码!");//处理登录失败
        break;
    default:
        break;
    }
}
/*登录成功打开好友列表界面,保存自己和好友的数据并将这些数据传给好友列表的类*/
void LoginDialog::deelUserLoginSuc(QString jsonstr)
{
   
   
    //定义结构体接收自己的数据
    UserData hostData;
    //解析json
    vector<UserData> friends = MsgBuilder::parseLoginSucReturnMsg(hostData,jsonstr);
    //页面切换
    FriendList *f = new FriendList(hostData,friends);
    f->show();
    //关掉登录页面
    this->close();
}
/*这个页面关闭后,停止对服务器信号的监听*/
void LoginDialog::closeEvent(QCloseEvent *)
{
   
   
    //断开连接  断开哪个信号 断开哪个槽函数
    disconnect(socket,SIGNAL(readyRead()),this,SLOT(slot_read()));
}

四,好友列表实现

创建窗口

登录成功后,由登录界面进入本界面

/*自定义的构造函数,接收由服务器发送的用户信息和好友列表信息*/
FriendList::FriendList(UserData user,vector<UserData> friends,QWidget *parent) :
    QDialog(parent),
    ui(new Ui::FriendList)
{
   
   
    ui->setupUi(this);
    //初始化
    this->user = user;
    this->friends = friends;
    socket = MySocket::getIns();
    socket->setSelf(user);//保存到全局使用的类中
    //连接函数
    connect(socket,SIGNAL(readyRead()),this,SLOT(slot_read()));
    //显示自己的信息
    QString str = QString("%1(%2)").arg(user.nickname).arg(user.id);
    ui->label->setText(str);
    //显示好友信息
    showFriends();
}

自定义控件的构建

/*单个自定义控件中显示的都是好友信息,因此此处的data储存的是单个好友的信息*/
FriendForm::FriendForm(UserData data,QWidget *parent) :
    QWidget(parent),
    ui(new Ui::FriendForm),fdata(data)
{
   
   
    ui->setupUi(this);
    //显示图片
    QPixmap p(":/heads/head1.jpg");
    p = p.scaled(ui->label_img->size());
    ui->label_img->setPixmap(p);
    //显示好友信息
    QString str = QString("%1(%2)").arg(data.nickname).arg(data.id);
    ui->label_name->setText(str);
}

功能实现

1.显示在线好友
/*在列表中通过储存着好友信息的容器显示好友信息*/
void FriendList::showFriends()
{
   
   
    //遍历好友容器
    for(vector<UserData>::iterator it=friends.begin();it!=friends.end();it++)
    {
   
   
        /*FriendForm继承QWidge*/
        //创建自定义控件
        FriendForm *f = new FriendForm(*it,ui->listWidget);
        //创建行对象
        QListWidgetItem *i = new QListWidgetItem(ui->listWidget);
        //修改行对象的尺寸
        i->setSizeHint(f->size());
        //三者绑定
        ui->listWidget->setItemWidget(i,f);
    }
}
2.好友上线
/*有好友上线,服务器发出信号,调用slot_read函数*/
void FriendList::slot_read()
{
   
   
    //获取接收消息
    QBy
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值