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());
}
- 返回id->MsgBuilder类
/*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

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

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



