一、客户端涉及到UI界面的跳转和回显
代码实现思路:
1.1、界面跳转通过信号槽实现,登录界面完成后,发送信号给主界面,同时主界面通过信号函数获取服务端信息,从而建立socket,实现网络通信;
1.2、数据库记录现有用户列表,并建立对应的UI索引,因为每次在主界面双击时,就要弹出新的UI以实现多对多聊天;
1.3、主界面控制socket的收发,socket收发后依据字符流控制消息流向哪个打开UI界面,实现多对多聊天消息分发及隔离;
1.4、运行后的效果如图:
图1.登录界面 图2.主界面
图3.聊天界面
二、代码如下:
salite记录数据相关文件:
cpp文件:(其实和服务端的相同)
/*--------------------------------------------------------
* Author : Firdin
* E-mail : firdin@yeah.net
* File Name : server_sqlite.c
* Created Time: 2017年10月12日 星期四 15时27分11秒
* Introduction:
*
*-------------------------------------------------------*/
#include "server_sqlite.h"
#include<QDebug>
#include<QString>
bool server_sqlite::sqlite_init()
{
if(QSqlDatabase::contains("qt_sql_default_connection"))
my_db=QSqlDatabase::database("qt_sql_default_connection");
else
my_db=QSqlDatabase::addDatabase("QSQLITE");//创建sqlite数据库文件
if(!my_db.isValid())
{
qDebug()<<"数据库创建失败"<<endl;
return false;
}
my_db.setDatabaseName("E:\\user_client.db");//将数据库文件存放在C盘,且名字为user_info.db
if(!my_db.open())//判断数据库打开是否正常
{
qDebug()<<"数据库文件打开失败";
return false;
}
else
{
qDebug()<<"数据库文件已打开";
}
QSqlQuery search;//数据库语句执行
temp="create table user(id INT,name VARCHAR(15),IP VARCHAR(15),state VARCHAR(8))";//数据库表单:ID、用户名、IP地址、在线与否
//qDebug()<<"创建表单:"<<temp;
if(!search.exec(temp))//判断数据库语句执行是否正常
{
qDebug()<<"表单创建失败,原因:已存在数据库表单或文件读取错误,请检查!!";
}
sqlite_delete_all();
return true;
}
bool server_sqlite::sqlite_insert(int id_s,QString name_t,QString IP_t)//插入新的用户信息到数据库表单,格式:用户名、用户IP地址(字符串形式)
{
temp.clear();
temp.sprintf("insert into user values(%d,'%s','%s','在线')",id_s,name_t.toStdString().data(),IP_t.toStdString().data());
QSqlQuery search;//数据库语句执行
if(!search.exec(temp))
{
qDebug()<<"插入数值失败,请检查!!";
return false;
}
count++;
return true;
}
bool server_sqlite::sqlite_delete(QString name_m)//删除表单中某一个元素
{
temp.clear();
temp.sprintf("delete from user where name = '%s'",name_m.toStdString().data());
QSqlQuery search;//数据库语句执行
if(!search.exec(temp))
{
qDebug()<<"删除数值失败,请检查!!";
return false;
}
return true;
}
bool server_sqlite::sqlite_delete_all()//删除表单中所有元素
{
temp.clear();
temp="delete from user";
QSqlQuery search;//数据库语句执行
if(!search.exec(temp))
{
qDebug()<<"删除所有数值失败,请检查!!";
return false;
}
return true;
}
QString* server_sqlite::sqlite_search(QString name_s)//依据用户名查找对应的信息
{
QString *des=new QString;
temp.clear();
temp.sprintf("select id,name,IP,state from user where name = '%s' ",name_s.toStdString().data());
QSqlQuery search;//数据库语句执行
if(!search.exec(temp))
{
qDebug()<<"查找指定数值失败,请检查!!";
return NULL;
}
while(search.next())
{
*des+=search.value(1).toString()+" "+search.value(2).toString()+" "+search.value(3).toString()+"\n";
}
return des;
}
bool server_sqlite::sqlite_update(QString name_u,QString state_u)//修改用户在线信息
{
temp.clear();
temp.sprintf("update user set state = '%s' where name = '%s'",state_u.toStdString().data(),name_u.toStdString().data());
QSqlQuery search;//数据库语句执行
if(!search.exec(temp))
{
qDebug()<<"修改指定用户状态失败,请检查!!";
return false;
}
return true;
}
QString* server_sqlite::sqlite_online_server()//显示当前在线用户信息
{
QString *temp=new QString;
QSqlQuery search;//数据库语句执行
search.exec("select * from user");
while(search.next())
{
if( "offline" != search.value(3))
{
//qDebug()<<"用户名:"<<search.value(1).toString()<<"IP地址:"<<search.value(2).toString()<<endl;
*temp+=search.value(1).toString()+" "+search.value(2).toString()+"\n";
}
}
//qDebug()<<"原始信息拼接:"<<*temp;
return temp;
}
QString* server_sqlite::sqlite_offline_server()//显示当前不在线用户信息
{
QString *temp=new QString;
QSqlQuery search;//数据库语句执行
search.exec("select * from user");
while(search.next())
{
if("online" != search.value(3))
*temp+=search.value(1).toString()+" "+search.value(2).toString()+"\n";
}
// qDebug()<<"不在线用户信息:"<<*temp;
return temp;
}
bool server_sqlite::sqlite_delete_table()//删除表单(表单为临时配置文件,因此可以删除)
{
temp.clear();
temp.sprintf("drop table user");
QSqlQuery search;//数据库语句执行
if(!search.exec(temp))
{
qDebug()<<"删除表单失败,请检查!!";
return false;
}
return true;
}
int server_sqlite::sqlite_search_id(QString name_src)
{
temp.clear();
temp.sprintf("select id from user where name = '%s'",name_src.toStdString().data());
QSqlQuery search;
//qDebug()<<temp;
if(!search.exec(temp))
{
qDebug()<<"表单查询失败,请检查!!";
return -1;
}
if(search.first())
{
//qDebug()<<"所查ID为:"<<search.value(0).toInt();
return search.value(0).toInt();
}
return -1;
}
QString* server_sqlite::sqlite_search_IP(QString name_s)//查找制定用户的IP地址
{
QString *t=new QString;
temp.clear();
temp.sprintf("select IP from user where name = '%s'",name_s.toStdString().data());
QSqlQuery search;
//qDebug()<<temp;
if(!search.exec(temp))
{
qDebug()<<"表单查询失败,请检查!!";
return NULL;
}
if(search.first())
{
//qDebug()<<"所查IP为:"<<search.value(0).toInt();
*t=search.value(0).toString();
return t;
}
return NULL;
}
H文件
#ifndef server_sqlite_H
#define server_sqlite_H
#include <QSqlDatabase>
#include <QSqlRecord>
#include <QSqlQuery>
#include <QSqlError>
#include <QDebug>
class server_sqlite //无继承的类(独立数据库操作类)
{
private:
QSqlDatabase my_db;//用户数据表单建立
int count;//用户在线人数
QString temp;//用于拼接字符用的临时变量
QString output;//用于输出用户信息
public:
explicit server_sqlite()
{
count=0;
temp.clear();
}
bool sqlite_init();//初始化数据库用成员函数
bool sqlite_insert(int id_s,QString name_t,QString IP_t);//插入数据
bool sqlite_delete(QString name_m);//删除一条数据
bool sqlite_delete_all();//删除所有的数据
QString* sqlite_search(QString name_s);//查找指定用户数据
QString* sqlite_search_IP(QString name_s);//查找制定用户的IP地址
bool sqlite_update(QString name_u,QString state_u);//修改指定用户的在线与否信息
QString* sqlite_online_server();//输出在线用户信息,通过判断state是否是online
QString* sqlite_offline_server();//输出历史用户(不在线但是有其信息)
bool sqlite_delete_table();//删除表单(表单为临时配置文件,因此可以删除)
int sqlite_search_id(QString name_src);//依据名字查询ID号,ID号在转发数据时需要用于查找QList中的socket对象,以达到准确转发消息
~server_sqlite()
{
my_db.close();
}
};
#endif
登录UI的代码实现:
cpp代码实现:
#include "my_login.h"
#include "ui_my_login.h"
#include<QPainter>
My_Login::My_Login(QWidget *parent) :
QDialog(parent),
ui(new Ui::My_Login)
{
ui->setupUi(this);
this->setFixedSize(318,264);//设置窗体大小固定
this->setWindowTitle("登陆到服务器");
Img=QImage(":/bk_login");
//点击响应
connect(ui->pushButton_login,SIGNAL(clicked(bool)),this,SLOT(slot_send()));
}
My_Login::~My_Login()
{
delete ui;
}
void My_Login::slot_send()//发送信息到主窗体(信号槽)
{
if(ui->lineEdit_username->text().isEmpty() || ui->lineEdit_IPAddr->text().isEmpty() || ui->lineEdit_IP_Port->text().isEmpty())
{
QMessageBox::warning(this,"警告","请输入完整登陆信息后再登陆!",QMessageBox::Ok,QMessageBox::Cancel);
}
else
{
QString send_info;
send_info+=ui->lineEdit_username->text()+":"+ui->lineEdit_IPAddr->text()+":"+ui->lineEdit_IP_Port->text();
emit send_data(send_info);
}
}
void My_Login::paintEvent(QPaintEvent *event)//绘制背景
{
QPainter pt(this); //定义一个在当前窗口画画的画家
QImage drawing = Img.scaled(this->width(),this->height());
pt.drawImage(0,0,drawing,0,0,this->width(),this->height());
update();
}
H文件:
#ifndef MY_LOGIN_H
#define MY_LOGIN_H
#include <QDialog>
#include <QHostAddress>
#include <QHostInfo>
#include <QNetworkInterface>
#include <QProcess>
#include<QTcpServer>
#include<QTcpSocket>
#include<QMessageBox>
#include<QImage>
#include<QPaintEvent>
namespace Ui {
class My_Login;
}
class My_Login : public QDialog
{
Q_OBJECT
public:
explicit My_Login(QWidget *parent = 0);
void paintEvent(QPaintEvent *event);
~My_Login();
private:
Ui::My_Login *ui;
QImage Img;
signals:
void send_data(QString);
private slots:
void slot_send();
};
#endif // MY_LOGIN_H
聊天界面的实现:
cpp文件的实现:
#include "my_chart.h"
#include "ui_my_chart.h"
#include<QStringList>
#include<QMessageBox>
#include<QTextStream>
#include <QPainter>
#include <QPixmap>
My_Chart::My_Chart(QWidget *parent) :
QDialog(parent),
ui(new Ui::My_Chart)
{
ui->setupUi(this);
this->setFixedSize(653,441);
ui->textEdit_show_message->setReadOnly(true);
//点击响应
connect(ui->pushButton_send,SIGNAL(clicked(bool)),this,SLOT(slot_send_message()));
}
My_Chart::~My_Chart()
{
delete ui;
}
void My_Chart::setIP_min(QString res)//显示本机IP地址和聊天对象的IP地址
{
QStringList analysis=res.split(";");
ui->label_show_mine->setText(analysis.at(0));//显示本机IP地址
ui->label_show_other_side->setText(analysis.at(1));//显示对方的IP地址
}
void My_Chart::show_message(QString src)//接收主窗体的字符串并显示到聊天界面上去
{
QStringList analysis=src.split(":");//依据符号对原始字符串进行分割
ui->textEdit_show_message->append(analysis.at(0)+":\n"+analysis.at(1));//将对方的消息内容显示在窗体上
}
void My_Chart::set_names_client(QString src)//传送用户姓名和接收方姓名
{
QStringList analysis=src.split(":");
name_local=analysis.at(0);
username=analysis.at(1);//设置用户名
}
void My_Chart::slot_send_message()//发送消息
{
QString mess="message:";//消息拼接
QString temp;//取出聊天内容
temp.clear();
QTextStream out(&temp);//从textEdit中读取内容
out << ui->textEdit_input_message->toPlainText();//保存成为html格式//保存到文件中
//qDebug()<<"对话框中的内容"<<temp;
if(temp.isEmpty())
{
QMessageBox::warning(this,"提示","请输入消息后再尝试发送!!",QMessageBox::Ok,QMessageBox::Cancel);//没有输入消息则弹窗警示
qDebug()<<"无消息可发送!!";
}
else
{
mess+=name_local+"|"+username+":"+temp;
//qDebug()<<"发送的消息内容"<<mess;
ui->textEdit_input_message->clear();//清除输入框中的字符
QByteArray message;
QDataStream out(&message,QIODevice::WriteOnly);
out.setVersion(QDataStream::Qt_5_7);
out<<mess;
qDebug() << "发送消息:" << mess;
Socket_login->write(message);
qDebug()<<"消息已发出!";
ui->textEdit_show_message->append(name_local + ":\n" + temp);
}
}
void My_Chart::set_Socket_local(QTcpSocket *Socket_src)
{
Socket_login=Socket_src;
}
void My_Chart::paintEvent(QPaintEvent *event)
{
QPainter painter(this);
painter.drawPixmap(0,0,width(), height(),QPixmap(":/10.jpg"));
}
H文件实现:
#ifndef MY_CHART_H
#define MY_CHART_H
#include <QDialog>
#include <QHostAddress>
#include <QHostInfo>
#include <QNetworkInterface>
#include <QProcess>
#include <QPainter>
#include <QPixmap>
#include<QTcpServer>
#include<QTcpSocket>
namespace Ui {
class My_Chart;
}
class My_Chart : public QDialog
{
Q_OBJECT
public:
explicit My_Chart(QWidget *parent = 0);
void setIP_min(QString res);//显示本地IP地址(测试用)
void show_message(QString src);//接收主窗体的字符串并显示到聊天界面上去
void set_names_client(QString src);//传送聊天双方的名字
void set_Socket_local(QTcpSocket *Socket_src);//将Socket传送过来,在聊天窗口实现发送消息,减轻主窗体的网络负担
void paintEvent(QPaintEvent *event);
~My_Chart();
/*
signals:
void send_message(QString);
*/
private slots:
void slot_send_message();//发送消息到一个指定的用户(指定用户为打开的聊天界面是和谁在聊天)
private:
Ui::My_Chart *ui;
QString username;//聊天对像的名字(用于发送信息)
QString name_local;//本家姓名(发起聊天的我的用户名)
QTcpSocket *Socket_login;//接受主窗体的网络文件描述符
};
#endif // MY_CHART_H
主界面的代码实现:
cpp文件实现:
#include "mainwindow.h"
#include "ui_mainwindow.h"
#include<QPicture>
#include<QDebug>
MainWindow::MainWindow(QWidget *parent) :
QWidget(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);
user_count=2;
current_user=0;
this->setFixedSize(252,532);//设置窗体大小固定,数值源自UI设计图形界面
this->setWindowTitle("FeiQ低配版");//设置窗体的名称
get_IP_Address();//获取本机IP地址并显示
//初始化数据库
my_client.sqlite_init();//初始化数据库,为聊天用户建立一个在线用户表单
//控件动作响应
connect(Login_u,SIGNAL(send_data(QString)),this,SLOT(slot_recv(QString)));//登陆窗体动作响应
connect(ui->listWidget_onlineuser_list,SIGNAL(itemDoubleClicked(QListWidgetItem*)),this,SLOT(slot_select_user(QListWidgetItem*)));//双击用户列表动作响应
Login_u->show();//显示登陆界面
}
MainWindow::~MainWindow()//析构函数
{
qDebug()<<"退出聊天程序";
QString mess="exit:"+username_local+":"+IP_Addr;
QByteArray message;
QDataStream out(&message,QIODevice::WriteOnly);
out.setVersion(QDataStream::Qt_5_7);
out<<mess;
qDebug() << "退出信息:" << mess;
Socket_login->write(message);
qDebug()<<"消息已发出!";
delete ui;
}
void MainWindow::slot_recv(QString res)//核对登陆信息并控制窗体切换
{
QStringList analysis=res.split(":");
Img=QImage(":/bk_Main.png");
Server_IP=analysis.at(1);
QString Port_server=analysis.at(2);
Socket_login=new QTcpSocket(this);
Socket_login->abort();
//qDebug()<<"服务器IP地址:"<<Server_IP<<"端口号:"<<Port_server.toInt();
Socket_login->connectToHost(Server_IP,Port_server.toInt());//连接到服务器,connectToHost函数为虚函数,无返回值
connect(Socket_login,SIGNAL(readyRead()),this,SLOT(slot_recv_Message()));//数据读取响应连接到读取函数
if(!Socket_login->waitForConnected(10000))
{
QMessageBox::warning(Login_u,"网络连接错误","未连接到网络,请稍后重试!",QMessageBox::Ok,QMessageBox::Cancel);
}
else
{
this->show();
//设置用户头像(label控件)
Login_u->close();//关闭登陆界面
ui->label_show_username->setText(analysis.at(0));
username_local=analysis.at(0);
QString string="user:"+username_local+":"+IP_Addr;//拼接消息为格式:user:uesrname:IPAddr
QByteArray message;
QDataStream out(&message,QIODevice::WriteOnly);
out.setVersion(QDataStream::Qt_5_7);
out<<string;
Socket_login->write(message);
}
}
void MainWindow::slot_select_user(QListWidgetItem *src)//双击用户名弹出聊天界面
{
QString temp=src->text();//获取当前双击用户的名字
QString *IP_temp=my_client.sqlite_search_IP(temp);
int ID=my_client.sqlite_search_id(temp);//在数据库中查找对应的ID号
if(-1 != ID)
{
Chart_u[ID].setWindowTitle("和"+temp+"聊天中");//依据ID号建立一个子窗口
Chart_u[ID].setIP_min(IP_Addr+";"+*IP_temp);//显示聊天界面上的IP地址
Chart_u[ID].set_names_client(username_local+":"+temp);//传送聊天双方的名字到聊天窗口
Chart_u[ID].show();//显示子窗体
Chart_u[ID].set_Socket_local(Socket_login);//传送文件描述符,以便窗体发送消息
}
else
{
qDebug()<<"ID号查询失败,请检查数据库文件!!";
}
}
void MainWindow::get_IP_Address()//获取本机IP地址并解析IPV4地址(源自网络)
{
QHostInfo info = QHostInfo::fromName(QHostInfo::localHostName());//首先获取本机名称,其次依据本机名称获的本机IP地址
info.addresses();//QHostInfo的address函数获取本机ip地址
//存在多条ip地址ipv4和ipv6:
foreach(QHostAddress address,info.addresses())//该语句为从集合中每个成员中进行筛选:for each member进行遍历
{
if(address.protocol()==QAbstractSocket::IPv4Protocol)//只取ipv4协议的地址
{
ui->label_showIPAddr->setText(address.toString());
IP_Addr=address.toString();
}
}
//qDebug()<<"IPv4地址:"<<IP_Addr;
}
void MainWindow::paintEvent(QPaintEvent *event)//绘制背景
{
QPainter pt(this); //定义一个在当前窗口画画的画家
QImage drawing = Img.scaled(this->width(),this->height());
pt.drawImage(0,0,drawing,0,0,this->width(),this->height());
update();
}
void MainWindow::slot_recv_Message()//接受数据响应函数
{
QDataStream in(Socket_login);//定义数据流
in.setVersion(QDataStream::Qt_5_7);//规定QT网络版本
QString recv_Message;
in >> recv_Message;
if(recv_Message.isEmpty())
{
QMessageBox::warning(this,"警告","网络错误,请检查网络连接!",QMessageBox::Ok,QMessageBox::Cancel);//如果,没有接收到信息,则网络出错,没有数据
}
else
network_server(recv_Message);//接受到信息,则进入字符分解程序
}
void MainWindow::network_server(QString src)//网络服务函数
{
QMap<QString,int> map;//以QMap形式将字符串与整型一一对应
map.insert("user",0);//接受到用户列表信息
map.insert("message",1);//接收到消息
map.insert("file",2);//接收到除音乐、图片、视频外的文件
//由于多媒体文件可以预览,因此将其与其他文件分开,同时压缩文件也应该与其他的分开,以下功能以后再实现
map.insert("video",3);//接收到视频文件
map.insert("picture",4);//接收到图片文件
map.insert("music",5);//接收到音乐文件
map.insert("ZIP",6);//接收到压缩包文件
map.insert("DIR",7);//接收到带有目录的文件
map.insert("",888);//无数据时的错误码
QStringList info = src.split(":");//收到的字符串以“:”为分割标志对其进行分解,并存入字符数组(列表)中,以便后期使用
//user:kk;mm;:192.168.132.108;192.168.1.140; 传输用户列表
//message:username:Hello There! 传输消息
//file:username:filename 传输文件
//qDebug() << "类型:" << info[0]<< " 对方姓名" << info[1]<< " 内容:" << info[2];
switch(map[info.at(0)])
{
case 0:
refresh_userinfo(info.at(1)+":"+info.at(2));//刷新用户列表信息(依据服务器发送信息刷新,无需本地定时)
break;
//接收到服务器转发的消息,消息类型:message:username:Hello There!!
case 1:
qDebug()<<"接收到服务器的消息:"<<info;
splite_message(info.at(1)+":"+info.at(2));//将接收的消息继续拼合分发下去,让子函数继续解析字符串
break;
case 2:
qDebug()<<"此功能待开发";
break;
case 3:
qDebug()<<"此功能待开发";
break;
case 4:
qDebug()<<"此功能待开发";
break;
case 5:
qDebug()<<"此功能待开发";
break;
case 6:
qDebug()<<"此功能待开发";
break;
case 7:
qDebug()<<"此功能待开发";
break;
case 888:
qDebug()<<"接收数据出错,请检查!!";
default:
break;
}
}
void MainWindow::refresh_userinfo(QString src)//刷新用户列表信息
{
QStringList source=src.split(":");//将名字和IP分开
if("" != source.at(0) && ""!=source.at(1))
{
QString names=source.at(0);//获取所有在线用户的名字
QString IPs=source.at(1);//获取所有在线用户对应的IP地址(名字与IP对应,与服务端约定名字、IP分开且对应)
QStringList name_dis=names.split(";");//依据符号";"来区分不同用户名
QStringList IP_dis=IPs.split(";");//分割IP地址
if(""!=name_dis.at(0)&&""!=IP_dis.at(0)&&name_dis.length()>=1&&IP_dis.length()>=1)
{
QString name_client;//临时变量存放用户名
QIcon user_list_logo(":/user_list.png");
ui->listWidget_onlineuser_list->clear();//清除之前的用户列表
for(int i=0;i<name_dis.length();i++)//将名字显示在列表中,将用户列表放在数据库文件中
{
my_client.sqlite_insert(i,name_dis.at(i),IP_dis.at(i));//将获取的用户信息加入数据库(i即为其ID,多个Dialog中传输消息依靠ID来区分)
name_client=name_dis.at(i);//获取名称
if(""!=name_dis.at(i))
{
QListWidgetItem *temp_list = new QListWidgetItem(user_list_logo,name_client);//合成list元素
ui->listWidget_onlineuser_list->addItem(temp_list);//加入列表显示
}
}
}
}
//qDebug()<<"在线用户信息刷新完成!!";
}
void MainWindow::splite_message(QString src)//将从服务器接受的消息依据接收用户名分发到各自的窗口上
{
qDebug()<<"分发消息服务函数:"<<src;
QStringList analysis=src.split(":");//拆分字符串
QString username=analysis.at(0);//解析收发双方
QStringList user_aim=username.split("|");//分解字符串,取出收发双方姓名
int ID=my_client.sqlite_search_id(user_aim.at(0));//分解后第一个字符串为聊天对象,查找到对方的ID号,用ID来识别窗口
if(-1 == ID)
qDebug()<<"ID号查询失败,无法继续分发消息,请检查!!";
else
{
qDebug()<<"查询的ID号为:"<<ID;
Chart_u[ID].show_message(user_aim.at(0)+":"+analysis.at(1));//发送消息到子窗体上
}
}
H文件的实现:
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QWidget>
//主窗体用户列表使用
#include<QListWidgetItem>
#include"my_chart.h"//添加聊天窗体类
#include"my_login.h"//添加登陆窗体类
//添加网络类
#include <QHostAddress>
#include <QHostInfo>
#include <QNetworkInterface>
#include <QProcess>
//创建套接字使用
#include<QTcpServer>
#include<QTcpSocket>
//解析字符串使用
#include<QStringList>
//绘制背景图片以及头像使用
#include<QImage>
#include<QPainter>
#include<QPixmap>
#include<QMessageBox>
#include<QMap>
#include"server_sqlite.h"//自定义sqlite控制类
namespace Ui {
class MainWindow;
}
class MainWindow : public QWidget
{
Q_OBJECT
public:
explicit MainWindow(QWidget *parent = 0);
void get_IP_Address();
void paintEvent(QPaintEvent *event);
void network_server(QString src);//用于分析字符串并作出相应的响应
void refresh_userinfo(QString src);//该函数用于刷新在线用户信息
void splite_message(QString src);//将从服务器接受的消息依据接收用户名分发到各自的窗口上(由于可以同时和多人聊天,故该部分很必要)
~MainWindow();
private slots:
void slot_recv(QString res);
void slot_select_user(QListWidgetItem *src);
void slot_recv_Message();
private:
Ui::MainWindow *ui;
server_sqlite my_client;//定义一个数据库对象
int user_count,current_user;//用于记录用户数量和当前打开窗口数
QTcpSocket *Socket_login;//用于登陆和聊天的文件描述符
My_Login *Login_u=new My_Login;//登录界面对象,仅显示一个
My_Chart Chart_u[10];//聊天界面子窗口(最多打开10个)
QString IP_Addr;//本机IP地址
QString Server_IP;//服务器IP地址
QImage Img;//背景图片
QPicture *pix;//图像图片
QString username_local;
};
#endif // MAINWINDOW_H
main.c实现
#include "mainwindow.h"
#include <QApplication>
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
MainWindow w;
//w.show();
return a.exec();
}
UI界面过多,参考图片吧!