网站维护 收录,网页设计与制作教程第二版考试,建筑工程集团有限公司,江西南昌赣州抚州萍乡一百一十九、简易版网络聊天室实现
119.1 QT实现连接TCP协议
119.1.1 基于TCP的通信流程 119.1.2 QT中实现服务器过程
使用QTcpServer实例化一个服务器对象设置监听状态#xff0c;通过listen()函数#xff0c;可以监听特定的主机#xff0c;也可以监听所有客户端#x…一百一十九、简易版网络聊天室实现
119.1 QT实现连接TCP协议
119.1.1 基于TCP的通信流程 119.1.2 QT中实现服务器过程
使用QTcpServer实例化一个服务器对象设置监听状态通过listen()函数可以监听特定的主机也可以监听所有客户端端口号可以是系统自动分配的也可以是指定端口号。如果有客户端发来连接请求那么服务器就自动发射一个newConnection信号我们就可以将该信号连接到自定义的槽函数中处理该客户端的操作。此时服务器和客户端已经建起了连接可以调用nextPandingConnection获取最新连接的客户端套接字可以将该套接字存放在服务器的客户端容器中。当客户端发来数据时该客户端就会自动发射一个readyRead信号我们可以将该信号连接到自定义的槽函数中读取客户端数据。通过read(),readLine(),readAll()读取套接字里的数据可以通过write()往套接字中写入数据关闭服务器使用close即可
119.1.3 QT中实现客户端过程
使用QTcpSocket实例化一个客户端对象将客户端连接到服务器使用connectToHost, 给定主机地址端口号如果连接成功该客户端会自动发射connected信号我们可以将该信号连接到自定义的槽函数中处理相关逻辑代码。此时客户端和服务器已经建立了连接如果服务端发来数据那么该客户端会自定发射readyRead信号可以将该信号连接到自定义的槽函数中读取服务端中数据可以使用read() readLine() readAll()读取套接字中数据使用write往套接字中写入数据客户端断开与服务器的连接使用disConnectFromHost, 如果断开成功客户端会自动发射disconnected信号我们可以将该信号连接到自定义的槽函数中处理相关逻辑代码。
119.2 服务器端
119.2.1 UI 界面 119.2.2 qt_server.h
#ifndef QT_SERVER_H
#define QT_SERVER_H#include QWidget
#include QTcpServer
#include QList
#include QTcpSocket
#include QMessageBox
#include QDebugQT_BEGIN_NAMESPACE
namespace Ui { class Qt_Server; }
QT_END_NAMESPACEclass Qt_Server : public QWidget
{Q_OBJECTpublic:Qt_Server(QWidget *parent nullptr);~Qt_Server();private slots:void on_startBtn_clicked();public slots:// 自定义的 处理连接的槽函数声明void newConnection_slot();// 自定义的 处理接收数据的槽函数声明void readyRead_slot();private:Ui::Qt_Server *ui;QTcpServer *server;QListQTcpSocket * socketList;
};
#endif // QT_SERVER_H119.2.3 qt_server.cpp
#include qt_server.h
#include ui_qt_server.hQt_Server::Qt_Server(QWidget *parent): QWidget(parent), ui(new Ui::Qt_Server)
{ui-setupUi(this);// 给服务器指针创建空间server new QTcpServer(this);
// socketList new QList();
}Qt_Server::~Qt_Server()
{delete ui;
}// 点击启动服务器按钮对应的槽函数实现
void Qt_Server::on_startBtn_clicked()
{if(ui-startBtn-text() 启动服务器){// 获取UI界面上输入的端口号quint16 port ui-portEdit-text().toUInt();// 使服务器进入监听状态,返回值是bool类型if(server-listen(QHostAddress::Any,port)){QMessageBox::information(this,提示,服务器启动成功);}else{QMessageBox::critical(this,错误,服务器启动失败);}// 此时服务器已经进入监听状态,如果有客户端发来链接请求,// 则服务器会自动发射一个newConnection信号,需要将该信号连接到自定义的槽函数中处理连接的套接字connect(server, QTcpServer::newConnection, this, Qt_Server::newConnection_slot);ui-startBtn-setText(已启动服务器);ui-startBtn-setStyleSheet(background-color:green);}else{server-close();disconnect(server, QTcpServer::newConnection, this, Qt_Server::newConnection_slot);ui-startBtn-setStyleSheet(background-color:white);ui-startBtn-setText(启动服务器);}}// 自定义的 处理连接的槽函数声明
void Qt_Server::newConnection_slot()
{qDebug() 有新客户的连接;// 获取最新连接的客户端套接字,并放入容器中,此时客户端与服务器已经建立起连接QTcpSocket *s server-nextPendingConnection();socketList.push_back(s);// 如果有客户端发送数据,那么此客户端就会自动发射readyRead信号// 需要将该信号与自定义的处理接收数据的槽函数连接connect(s, QTcpSocket::readyRead, this, Qt_Server::readyRead_slot);
}// 自定义的 处理接收数据的槽函数实现
void Qt_Server::readyRead_slot()
{// 移除无效的客户端// 遍历所有的客户端for(int i0; isocketList.count(); i){// 判断每个客户端的状态,返回值是枚举类型// socketList.at(i)-state();if(0 socketList.at(i)-state()){// 移除当前客户端,通过下标删除socketList.removeAt(i);}}// 遍历容器,找到有需要读取数据的客户端for(int i0; isocketList.count(); i){// 如果当前客户端的 有效字节数 不为0,代表当前客户端有需要读取的数据if(0 ! socketList.at(i)-bytesAvailable()){// 读取客户端中的数据QByteArray msg socketList.at(i)-readAll();// 将读取的数据放到UI界面上ui-listWidget-addItem(QString::fromLocal8Bit(msg));// 将数据发送给所有客户端for (int j0; jsocketList.count(); j) {socketList.at(i)-write(msg);}}}
}119.2.4 main.cpp
#include qt_server.h#include QApplicationint main(int argc, char *argv[])
{QApplication a(argc, argv);Qt_Server w;w.show();return a.exec();
}119.3 客户端
119.3.1 UI 界面 119.3.2 qt_client.h
#ifndef QT_CLIENT_H
#define QT_CLIENT_H#include QWidget
#include QTcpServer
#include QList
#include QTcpSocket
#include QMessageBox
#include QDebugQT_BEGIN_NAMESPACE
namespace Ui { class Qt_Client; }
QT_END_NAMESPACEclass Qt_Client : public QWidget
{Q_OBJECTpublic:Qt_Client(QWidget *parent nullptr);~Qt_Client();public slots:void connected_slot();void readyRead_slot();private slots:void on_connectBtn_clicked();void on_msgBtn_clicked();void on_disconnectBtn_clicked();private:Ui::Qt_Client *ui;// 定一个客户端对象QTcpSocket *socket;// 定义一个用户名变量QString uname;
};
#endif // QT_CLIENT_H119.3.3 qt_client.cpp
#include qt_client.h
#include ui_qt_client.hQt_Client::Qt_Client(QWidget *parent): QWidget(parent), ui(new Ui::Qt_Client)
{ui-setupUi(this);// 给客户端对象创建空间socket new QTcpSocket(this);// 初始化UI界面的组件状态ui-msgEdit-setEnabled(false);ui-msgBtn-setEnabled(false);ui-disconnectBtn-setEnabled(false);}Qt_Client::~Qt_Client()
{delete ui;
}void Qt_Client::connected_slot()
{// 告诉服务器我进来了QString msg uname 来了,快接驾;// 将这个消息发送给服务器socket-write(msg.toLocal8Bit());// 此时说明服务器与客户端已经建立连接// 现在将UI界面的组件状态修改一下ui-msgEdit-setEnabled(true);ui-msgBtn-setEnabled(true);ui-disconnectBtn-setEnabled(true);ui-unameEdit-setEnabled(false);ui-ipEdit-setEnabled(false);ui-portEdit-setEnabled(false);ui-connectBtn-setEnabled(false);// 如果服务器发来数据客户端会自动发射readyRead信号// 因此需要将readyRead信号连接到自定义的槽函数// 因为只需要连接一次所以也是该在构造函数中写连接函数connect(socket, QTcpSocket::readyRead, this, Qt_Client::readyRead_slot);
}void Qt_Client::readyRead_slot()
{// 走到了这一步说明服务器给客户端发送了消息现在需要进行读取QByteArray msg socket-readAll();// 将这个数据放到UI界面的消息显示框中ui-listWidget-addItem(QString::fromLocal8Bit(msg));
}// 连接服务器按钮 对应的槽函数
void Qt_Client::on_connectBtn_clicked()
{// 获取UI界面的IP和PORT,还有unameQString ip ui-ipEdit-text();quint16 port ui-portEdit-text().toUInt();uname ui-unameEdit-text();// 使客户端连接服务器socket-connectToHost(ip, port);// 判断客户端是否成功连接服务器成功则客户端会自动发射connected信号// 将该信号连接到自定义的槽函数中// 因为只需要连接一次所以连接函数应该写在构造函数中connect(socket, QTcpSocket::connected, this, Qt_Client::connected_slot);
}void Qt_Client::on_msgBtn_clicked()
{// 获取UI界面上输入的内容QString msg uname : ui-msgEdit-toPlainText();// 将消息发送给服务器socket-write(msg.toLocal8Bit());}void Qt_Client::on_disconnectBtn_clicked()
{QString msg uname 走咯,我还会再回来的;// 将消息发送给服务器socket-write(msg.toLocal8Bit());// 断开链接socket-close();disconnect(socket, QTcpSocket::readyRead, this, Qt_Client::readyRead_slot);disconnect(socket, QTcpSocket::connected, this, Qt_Client::connected_slot);// 更改UI界面的组件状态ui-msgEdit-setEnabled(false);ui-msgBtn-setEnabled(false);ui-disconnectBtn-setEnabled(false);ui-unameEdit-setEnabled(true);ui-ipEdit-setEnabled(true);ui-portEdit-setEnabled(true);ui-connectBtn-setEnabled(true);
}119.3.4 main.cpp
#include qt_client.h#include QApplicationint main(int argc, char *argv[])
{QApplication a(argc, argv);Qt_Client w;w.show();return a.exec();
}一百二十、QT连接数据库
120.1 QT将数据库分为三个层次
数据库驱动层QSqlDriver、QSqlDriverCreator、QSqlDriverCreatorBase、QSqlDriverPluginsql接口层QSqlDatabase、QSqlQuery、QSqlRecord、QSqlError用户接口层提供一些模型QSqlQueryModel、QSqlTableModel、QSqlRelationalTableModel
120.2 实现数据库操作的相关方法
1. 添加数据库[static] QSqlDatabase QSqlDatabase::addDatabase(QSqlDriver *driver, const QString connectionName QLatin1String(defaultConnection)) QSQLITE SQLite version 3 or above
2. 设置数据库名称void QSqlDatabase::setDatabaseName(const QString name)
3. 包含数据库bool QSqlDatabase::contains(const QString connectionName QLatin1String(defaultConnection))
4. 打开数据库bool QSqlDriver::open(const QString db)
5. 关闭数据库void QSqlDatabase::close()
6. 错误信息QSqlError QSqlDatabase::lastError()7. sql语句执行构造一个QSqlQuery类对象调用其成员函数exec执行sql语句bool QSqlQuery::exec(const QString query)
8. bool QSqlQuery::next()遍历查询结果的函数120.3 示例
120.3.1 UI 界面 120.3.2 database.h
#ifndef DATABASE_H
#define DATABASE_H#include QWidget
#include QSqlDatabase // 数据库管理类
#include QSqlQuery // 数据库操作类
#include QSqlRecord // 数据库记录类
#include QSqlError // 数据库错误类
#include QMessageBox // 消息对话框类
#include QtDebugQT_BEGIN_NAMESPACE
namespace Ui { class DataBase; }
QT_END_NAMESPACEclass DataBase : public QWidget
{Q_OBJECTpublic:DataBase(QWidget *parent nullptr);~DataBase();private slots:void on_addBtn_clicked();void on_showAllEdit_clicked();void on_showEdit_clicked();void on_deleteBtn_clicked();void on_deleteAllBtn_clicked();private:Ui::DataBase *ui;// 实例化一个数据库对象QSqlDatabase db;
};
#endif // DATABASE_H120.3.3 database.cpp
#include database.h
#include ui_database.hDataBase::DataBase(QWidget *parent): QWidget(parent), ui(new Ui::DataBase)
{ui-setupUi(this);// 判断数据库是否存在if(!db.contains()){// 不存在则创建数据库db QSqlDatabase::addDatabase(QSQLITE); // 表示数据库驱动为sqlite3// 给刚创建的数据库起名db.setDatabaseName(stuInfo.db);// 提示用户数据库创建成功QMessageBox::information(this,提示,数据库创建成功);}// 打开数据库if(!db.open()){QMessageBox::critical(this,错误,数据库无法打开);return;}// 创建数据库表QSqlQuery table;// Sql语句QString sql create table if not exists stu_info_table(id integer primary key autoincrement,numb integer,name varchar(20),sex varchar(4),score integer);;if(table.exec(sql)){QMessageBox::information(this,提示,数据库学生表创建成功);}else{QMessageBox::critical(this,错误,数据库学生表创建失败);}
}DataBase::~DataBase()
{delete ui;
}// 添加
void DataBase::on_addBtn_clicked()
{// 获取UI界面上的信息int num ui-numEdit-text().toUInt();QString name ui-nameEdit-text();QString sex ui-sexEdit-text();int score ui-scoreEdit-text().toUInt();// 保证用户输入完整信息if(num 0 || name.isEmpty() || sex.isEmpty() || score 0){QMessageBox::warning(this,警告,请完善信息);return;}// 将信息存放到数据库学生表中QSqlQuery query;// SQL语句QString sql QString(insert into stu_info_table (numb, name, sex, score) values(%1,%2,%3,%4)).arg(num).arg(name).arg(sex).arg(score);// 执行SQL语句if(query.exec(sql)){QMessageBox::information(this,提示,数据添加成功);}else{QMessageBox::critical(this,错误,数据添加失败);}DataBase::on_showAllEdit_clicked();
}// 查看所有
void DataBase::on_showAllEdit_clicked()
{ui-tableWidget-clear();// 将信息存放到数据库学生表中QSqlQuery query;// SQL语句QString sql QString(select * from stu_info_table);// 执行SQL语句if(query.exec(sql)){// 将数据库的内容放到UI界面上int i 0; // 记录行号// 用next()遍历while (query.next()) {for(int j0; jquery.record().count(); j){ui-tableWidget-setItem(i,j,new QTableWidgetItem(query.value(j1).toString()));}i;}}
}// 查询某个学生
void DataBase::on_showEdit_clicked()
{QString name ui-nameEdit_2-text();if(name.isEmpty()){QMessageBox::information(this, 提示, 请输入要查询的学生姓名);return;}ui-tableWidget-clear();QSqlQuery query;QString sql QString(select * from stu_info_table where name%1;).arg(name);if(query.exec(sql)){int i0;while (query.next()) {// qDebug() i;for(int j0; jquery.record().count(); j){ui-tableWidget-setItem(i, j, new QTableWidgetItem(query.value(j1).toString()));}i;}}else{QMessageBox::warning(this, 警告, 查询错误);return;}
}void DataBase::on_deleteBtn_clicked()
{QString name ui-nameEdit_2-text();if(name.isEmpty()){QMessageBox::information(this, 提示, 请输入要删除的学生姓名);return ;}QString sql QString(delete from stu_info_table where name%1;).arg(name);QSqlQuery query;if(query.exec(sql)){QMessageBox::information(this, 提示, 删除成功);DataBase::on_showAllEdit_clicked();}else{QMessageBox::warning(this, 警告, 删除失败);DataBase::on_showAllEdit_clicked();}return ;
}void DataBase::on_deleteAllBtn_clicked()
{QString sql QString(delete from stu_info_table);QSqlQuery query;if(query.exec(sql)){QMessageBox::information(this, 提示, 删除成功);DataBase::on_showAllEdit_clicked();}else{QMessageBox::warning(this, 警告, 删除失败);DataBase::on_showAllEdit_clicked();}ui-tableWidget-clear();return ;
}120.3.4 main.cpp
#include database.h#include QApplicationint main(int argc, char *argv[])
{QApplication a(argc, argv);DataBase w;w.show();return a.exec();
}