QT--聊天室

avatar
作者
猴君
阅读量:0

一、设计要求

用QT做一个聊天室,

制作一个服务器和客户端。可以进行注册、登录,

登陆成功后可以使用昵称进行发送、接收消息。

能根据昵称、聊天内容查询历史记录,也可以查询全部聊天记录。

二、客户端三级ui界面

三、项目代码

//在pro文件里加入 QT       += core gui network RC_FILE += icon_config.rc
//客户端dialog.h #ifndef DIALOG_H #define DIALOG_H  #include <QtWidgets> #include <QDebug> // 网络连接类 #include <QTcpSocket> // 文本流 #include <QTextStream> #include <QDateTime> #include <QByteArray>  namespace Ui { class Dialog; }  class Dialog : public QDialog {     Q_OBJECT  public:     explicit Dialog(QWidget *parent = 0);     ~Dialog();  private:     Ui::Dialog *ui;     QTcpSocket *client;     void printMsg(QString); // 输出内容到公屏     void succRight();  private slots:     void btnConnClickedSlot(); // 连接按钮     void btnSendClickedSlot(); // 发送按钮     void connectedSlot(); // 连接成功的槽函数     void disconnectedSlot(); // 断开连接的槽函数     void readReadSlot(); // 接收数据的槽函数      void btnHisClickedSlot();//历史记录     void btnHisNameClickedSlot();//按照昵称     void btnHisNeiClickedSlot();//按照内容      void btnLoginClickedSlot();//登录/切换窗口      void btnRegClickedSlot();//注册    };  #endif // DIALOG_H 
//客户端dialog.c #include "dialog.h" #include "ui_dialog.h"  Dialog::Dialog(QWidget *parent) :     QDialog(parent),     ui(new Ui::Dialog) {     ui->setupUi(this);     // 抢前台     setWindowFlags(Qt::WindowStaysOnTopHint);      connect(ui->pushButtonConn,SIGNAL(clicked()),             this,SLOT(btnConnClickedSlot()));     connect(ui->pushButtonSend,SIGNAL(clicked()),             this,SLOT(btnSendClickedSlot()));      client = new QTcpSocket(this);     // 建立网络连接检测的信号槽     connect(client,SIGNAL(connected()),             this,SLOT(connectedSlot()));     connect(client,SIGNAL(disconnected()),             this,SLOT(disconnectedSlot()));     // 接收消息的信号槽     connect(client,SIGNAL(readyRead()),             this,SLOT(readReadSlot())); //历史     connect(ui->pushButtonHis,SIGNAL(clicked()),             this,SLOT(btnHisClickedSlot()));     connect(ui->pushButtonName,SIGNAL(clicked()),             this,SLOT(btnHisNameClickedSlot()));     connect(ui->pushButtonNei,SIGNAL(clicked()),             this,SLOT(btnHisNeiClickedSlot()));       //切换窗口:登录     connect(ui->pushButtonLo,SIGNAL(clicked()),             this,SLOT(btnLoginClickedSlot()));     //注册     connect(ui->pushButtonReg,SIGNAL(clicked()),             this,SLOT(btnRegClickedSlot()));  }  Dialog::~Dialog() {     disconnect(client,SIGNAL(disconnected()),                this,SLOT(disconnectedSlot()));     // 如果还在连接     if(client->isOpen())         client->close();     delete ui; }  void Dialog::btnConnClickedSlot() {     // 发起连接请求     // 默认用户输入的参数都对     client->connectToHost(ui->lineEditIp->text(),ui->spinBox->value()); }  void Dialog::printMsg(QString msg) {     // 获得当前时间     QString time = QDateTime::currentDateTime().toString("yyyy-MM-dd-hh:mm:ss");     ui->textBrowser->append(time);     ui->textBrowser->append(msg);     ui->textBrowser->append(""); }  void Dialog::succRight() {   ui->stackedWidget->setCurrentIndex(1); }  void Dialog::btnSendClickedSlot() {     // 获得昵称和消息内容     QString user = ui->lineEditUser->text();     if(user=="")     {         QMessageBox::warning(this,"提示","请输入昵称!");         return;     }     QString msg = ui->lineEditMsg->text();     if(msg == "")     {         QMessageBox::warning(this,"提示","请输入要发送的消息!");         return;     }      QString time = QDateTime::currentDateTime().toString("yyyy-MM-dd-hh-mm-ss");     // 创建文本流对象     QTextStream output(client);     // 连续输出发送     output << time<<":"<<user << ":" << msg;     // 清空消息输入框     ui->lineEditMsg->clear();     // 公屏显示     msg = user+QString("(本机):")+msg;     printMsg(msg); }  void Dialog::connectedSlot() {     // 屏蔽连接按钮,开启发送按钮     ui->pushButtonConn->setEnabled(false);     ui->pushButtonConn->setText("已连接");     ui->pushButtonSend->setEnabled(true);     ui->stackedWidget->setCurrentIndex(1); }  void Dialog::readReadSlot() {       QTextStream input(client);     QString text = input.readAll();     QString text1=input.readLine(100);      qDebug() <<text1;     QStringList list = text.split(":");     QStringList list2 = text1.split(":");     qDebug()<<"分割后数量"<<list.size();       qDebug() <<list2.size();      if(list.size()<4)     {     if(text=="dlchengg")     {         qDebug() <<text;         ui->stackedWidget->setCurrentIndex(2);         ui->textBrowser->clear();     } //    else if(list.size()==3) //    {   //        ui->textBrowser_2->append(text); //        return; //    }     else     {     printMsg(text);     }     }     else if(list.size()>=4)     {          ui->textBrowser_2->append(text);         return;     } }  void Dialog::btnHisClickedSlot() {      ui->textBrowser_2->clear();     QString user = ui->lineEditUser->text();     if(user=="")     {         QMessageBox::warning(this,"提示","请输入昵称!");         return;     }       QString time = QDateTime::currentDateTime().toString("yyyy-MM-dd-hh-mm-ss");     // 创建文本流对象      QTextStream output(client);     QString mm="历史记录";     output<< time<<":"<<user << ":" <<mm ; }  void Dialog::btnHisNameClickedSlot() {      ui->textBrowser_2->clear();     QString user = ui->lineEditUser->text();        QString time = "hh";     // 创建文本流对象      QTextStream output(client);     QString mm="按照昵称";     output<< time<<":"<<user << ":" <<mm ; }  void Dialog::btnHisNeiClickedSlot() {     ui->textBrowser_2->clear();     QString user = "sjdhs";      QString time = "按照内容";     // 创建文本流对象      QString msg = ui->lineEditMsg->text();      if(msg == "")      {          QMessageBox::warning(this,"提示","请输入要发送的消息!");          return;      }     QTextStream output(client);      output<< time<<":"<<user << ":" <<msg ; }  void Dialog::btnLoginClickedSlot() {     QString user = ui->lineEditUs->text();     if(user=="")     {         QMessageBox::warning(this,"提示","请输入昵称!");         return;     }     QString pwd = ui->lineEdit_2Pwd->text();     if(pwd == "")     {         QMessageBox::warning(this,"提示","请输入密码!");         return;     }      // 创建文本流对象     QTextStream output(client);     // 连续输出发送     QString mag="hha";     QString haf="lele";     output <<user << ":" << pwd<<":"<<mag<<":"<<haf;    }  void Dialog::btnRegClickedSlot() {     QString user = ui->lineEditUs->text();     if(user=="")     {         QMessageBox::warning(this,"提示","请输入昵称!");         return;     }     QString pwd = ui->lineEdit_2Pwd->text();     if(pwd == "")     {         QMessageBox::warning(this,"提示","请输入密码!");         return;     }      // 创建文本流对象     QTextStream output(client);     // 连续输出发送     output <<user << ":" << pwd; }  void Dialog::disconnectedSlot() {     // 开启连接按钮,屏蔽发送按钮     ui->pushButtonConn->setEnabled(true);     ui->pushButtonConn->setText("连接");     ui->pushButtonSend->setEnabled(false);     // 弹窗     printMsg("连接已断开!");     QMessageBox::warning(this,"提示","连接已断开!");     ui->stackedWidget->setCurrentIndex(0); } 
//服务器dialog.h #ifndef DIALOG_H #define DIALOG_H  #include <QtWidgets> #include <QDebug> // 连接管理类 #include <QTcpServer> #include <QDateTime> // 连接类 #include <QTcpSocket> // 文本流 #include <QTextStream>  #include <QButtonGroup> #include <QSqlDatabase> #include <QDebug> #include <QSqlError> #include <QMessageBox> #include <QSqlQuery> #include <QByteArray>   namespace Ui { class Dialog; }  class Dialog : public QDialog {     Q_OBJECT  public:     explicit Dialog(QWidget *parent = 0);     ~Dialog();  private:     Ui::Dialog *ui;     QTcpServer* server; // 管理对象(母鸡)     void printMsg(QString); // 输出内容到公屏     QTcpSocket* socket = NULL; // 连接对象(绿蛋)     QList<QTcpSocket*> sockets;     QList<QString> ips;      QSqlDatabase db;        void connect2DB(); // 连接到数据库1        void createTable();// 建表       void createTable2();       void insertData(); // 插入数据       void selectAll(int);  // 数据全查       void selectLOgin(QString,QString,int);        void selectName(QString,int);         void selectNei(QString,int);  private slots:     // 新连接来了的槽函数     void newConnSlot();     // 连接掉线的信号槽     void disconnetedSlot();     // 有数据可读时的槽函数     void readyReadSlot();  };  #endif // DIALOG_H 
//服务器dialog.c #include "dialog.h" #include "ui_dialog.h"  Dialog::Dialog(QWidget *parent) :     QDialog(parent),     ui(new Ui::Dialog) {     ui->setupUi(this);     // 抢前台     setWindowFlags(Qt::WindowStaysOnTopHint);      server = new QTcpServer(this);     // 连接新连接来了的信号槽     connect(server,SIGNAL(newConnection()),             this,SLOT(newConnSlot()));      // 开启监听服务     server->listen(QHostAddress::Any,8887);      connect2DB(); }  Dialog::~Dialog() {     if(server->isListening()) // 如果还在监听         server->close();     delete ui; }  void Dialog::printMsg(QString msg) {     // 获得当前时间     QString time = QDateTime::currentDateTime().toString("yyyy-MM-dd hh:mm:ss");     ui->textBrowser->append(time);     ui->textBrowser->append(msg);     ui->textBrowser->append(""); }  void Dialog::connect2DB() {     // 创建连接对象       db = QSqlDatabase::addDatabase("QSQLITE");       // 设置数据库的文件名称       db.setDatabaseName("book_management.db");       // 打开数据库       if(db.open())       {           qDebug() << "连接成功";           // createTable();          // createTable2();       }       else       {           // 获得错误信息封装类           QSqlError info = db.lastError();           // 提取错误文本           QString text = info.text();           // 展示错误           QMessageBox::critical(this,"错误",text);       }  }  void Dialog::createTable() {      QString sql = "CREATE TABLE book(time TEXT PRIMARY KEY,name TEXT,msg TEXT);";        // 创建数据库操作类对象       QSqlQuery sq;        if(sq.exec(sql))       {           qDebug() << "建表成功";       }else// 失败       {           // 获得错误信息封装类           QSqlError info = sq.lastError();           // 提取错误文本           QString text = info.text();           // 展示错误           qDebug() << text;       }   }  void Dialog::createTable2() {     QString sql2 = "CREATE TABLE class(name TEXT PRIMARY KEY,pwd TEXT);";        // 创建数据库操作类对象       QSqlQuery sq;        if(sq.exec(sql2))       {           qDebug() << "建表2成功";       }else// 失败       {           // 获得错误信息封装类           QSqlError info = sq.lastError();           // 提取错误文本           QString text = info.text();           // 展示错误           qDebug() << text;       } }  void Dialog::selectAll(int i) {      QString sql = "SELECT * FROM book";         QSqlQuery sq;        sq.prepare(sql);         if(sq.exec(sql))         {             // 清空上次显示           //  ui->textBrowser->clear();             while(sq.next())// 循环取出             {                 // 取出一条数据库中的字段                 QString time = sq.value(0).toString();                 QString name = sq.value(1).toString();                 QString msg = sq.value(2).toString();                  QString msa="历史";                 // 拼接并显示                 QString text = msa.append(":")+ time.append(":")+ name.append(":") + msg;                  QTextStream output(sockets.at(i));                 output<< text<<endl;             }         }   }  void Dialog::selectLOgin(QString user, QString pwd2,int i) {      QString name=user;      QString pwd=pwd2;        QString sql = "SELECT * FROM class WHERE name LIKE ? AND pwd LIKE ?;";        QSqlQuery sq;        sq.prepare(sql);         if(sq.exec(sql))         {             while(sq.next())             {                 qDebug() << "yes";                 QString user = sq.value(0).toString();                 QString pwd = sq.value(1).toString();                QString text ="dlchengg";                QTextStream output(sockets.at(i));                 output<<text;                   }         }                  else                  {                       QSqlError info = sq.lastError();                      // 提取错误文本                      QString text = info.text();                       text.prepend("登录失败:");                      QMessageBox::warning(this,"警告",text);         } }  void Dialog::selectName(QString name1,int i) {     QString name=name1;     QString sql = "SELECT * FROM book WHERE name LIKE ?";         QSqlQuery sq;        sq.prepare(sql);         sq.addBindValue(name);         if(sq.exec())         {              while(sq.next())// 循环取出             {                 // 取出一条数据库中的字段                 QString time = sq.value(0).toString();                 QString name = sq.value(1).toString();                 QString msg = sq.value(2).toString();                  QString msa="历史";                 // 拼接并显示                 QString text = msa.append(":")+time.append(":")+ name.append(":") + msg;                  QTextStream output(sockets.at(i));                 output<< text<<endl;             }         } }  void Dialog::selectNei(QString msg, int i) {      QString sql = "SELECT * FROM book WHERE msg LIKE ?";         QSqlQuery sq;        sq.prepare(sql);         sq.addBindValue(msg.prepend("%").append("%"));         if(sq.exec())         {              while(sq.next())// 循环取出             {                 // 取出一条数据库中的字段                 QString time = sq.value(0).toString();                 QString name = sq.value(1).toString();                 QString msg = sq.value(2).toString();                 QString msa="历史";                 // 拼接并显示                 QString text = msa.append(":")+time.append(":")+ name.append(":") + msg;                  QTextStream output(sockets.at(i));                 output<< text<<endl;             }         } }    void Dialog::newConnSlot() {     // 获得服务器端的连接类对象     socket = server->nextPendingConnection();     QTextStream output(socket);     // 如果满员则踢出     if(sockets.size() == 20)     {         qDebug() << "聊天室满员";         output << QString("聊天室已达人数上限,连接失败!");         socket->close();         return;     }     sockets.append(socket);     // 绿蛋收到消息的信号槽     connect(socket,SIGNAL(readyRead()),             this,SLOT(readyReadSlot()));     // 绿蛋掉线的信号槽     connect(socket,SIGNAL(disconnected()),             this,SLOT(disconnetedSlot()));     // 给客户端打个招呼     output << QString("服务器:你好啊!");     // 获得对面的IP地址和端口号     QString ip = socket->peerAddress().toString();     quint16 port = socket->peerPort();     QString portText = QString::number(port);      QString text = "新连接来了!";     text.append(ip).append(":").append(portText);     printMsg(text); }  void Dialog::disconnetedSlot() {     // 拿到发射者     socket = (QTcpSocket*)sender();      for(int i = 0;i<sockets.size();i++)     {         if(socket == sockets.at(i))         {             qDebug() << "第" << i << "个客户端掉线了";             // 获得对面的IP地址和端口号             QString ip = sockets.at(i)->peerAddress().toString();             quint16 port = sockets.at(i)->peerPort();             QString portText = QString::number(port);             QString text = "连接已断开!";             text.append(ip).append(":").append(portText);             printMsg(text);             sockets.removeAt(i);         }     } }   //接收数据 void Dialog::readyReadSlot() {     for(int i=0;i<sockets.size();i++)     {         if(sockets.at(i)->isReadable() && sockets.at(i)->bytesAvailable()>0)         {             qDebug() << "第" << i << "个客户端发的消息";             QTextStream input(sockets.at(i));             // 一口气都读了             QString text = input.readAll();             //写入数据库              QStringList list = text.split(":");             qDebug()<<"分割后数量"<<list.size();               if(list.size()==3)             {                 QString time = list[0];                QString name = list[1];                QString msg = list[2];                if(list[2]=="历史记录")              {               selectAll( i);              }               else if(list[2]=="按照昵称")               {                 selectName(name,i);               }               else if(list[0]=="按照内容")               {                 selectNei(msg,i);               }              else              {                 createTable();                 QString sql = "INSERT INTO book VALUES(?,?,?);";                 QSqlQuery sq;                     sq.prepare(sql);                     sq.addBindValue(time);                     sq.addBindValue(name);                     sq.addBindValue(msg);                      if(sq.exec())                         {                         qDebug()<<"数据插入成功";                            // QMessageBox::information(this,"通知","数据插入成功");                         }                         else                         {                             // 获得错误信息封装类                             QSqlError info = sq.lastError();                             // 提取错误文本                             QString text = info.text();                             // 展示错误                             text.prepend("数据插入失败:");                             QMessageBox::warning(this,"警告",text);                         }                     printMsg(text);                   for(int m=0;m<sockets.size();m++)                  {                     if(m==i)                         continue;                     QTextStream output(sockets.at(m));                     output << text;                  }                 }                }               else if(list.size()==2)             {                 createTable2();                QString name = list[0];                QString pwd = list[1];                 QString sql = "INSERT INTO class VALUES(?,?);";                 QSqlQuery sq;                     sq.prepare(sql);                     sq.addBindValue(name);                     sq.addBindValue(pwd);                     if(sq.exec())                         {                         qDebug()<<"注册成功";                            // QMessageBox::information(this,"通知","数据插入成功");                         }                         else                         {                             // 获得错误信息封装类                             QSqlError info = sq.lastError();                             // 提取错误文本                             QString text = info.text();                             // 展示错误                             text.prepend("注册失败:");                             QMessageBox::warning(this,"警告",text);                         }                   printMsg(text);                  for(int m=0;m<sockets.size();m++)                 {                     if(m==i)                         continue;                     QTextStream output(sockets.at(m));                     output << text;                 }               }             else if(list.size()==4)             {                  QString name = list[0];                 QString pwd = list[1];                 qDebug() << name<<pwd;                    QString sql = "SELECT * FROM class WHERE name=? AND pwd=?";                   QSqlQuery sq;                   sq.prepare(sql);                   sq.addBindValue(name);                   sq.addBindValue(pwd);                    qDebug() << "yes";                    if(sq.exec())                    {                             // 取出一条数据库中的字段                      while(sq.next())                 {                            QString name = sq.value(0).toString();                            QString pwd = sq.value(1).toString();                             qDebug() <<name<<pwd;                              qDebug() << "yes";                           QString text ="dlchengg";                           QTextStream output(sockets.at(i));                            output<<text;                  }                       }                     else                     {                                  QSqlError info = sq.lastError();                                 // 提取错误文本                                 QString text = info.text();                                  text.prepend("登录失败:");                                 QMessageBox::warning(this,"警告",text);                      }                   }                }         }    }  

四、项目结果

广告一刻

为您即时展示最新活动产品广告消息,让您随时掌握产品活动新动态!