• QT 第五天 TCP通信与数据库


    一、数据库增删改查

    1. QT += core gui sql
    2. greaterThan(QT_MAJOR_VERSION, 4): QT += widgets
    3. CONFIG += c++11
    4. # The following define makes your compiler emit warnings if you use
    5. # any Qt feature that has been marked deprecated (the exact warnings
    6. # depend on your compiler). Please consult the documentation of the
    7. # deprecated API in order to know how to port your code away from it.

    .h

    1. #ifndef WIDGET_H
    2. #define WIDGET_H
    3. #include
    4. #include //数据库管理类
    5. #include //执行sql语句对应的类
    6. #include //纪录类
    7. #include
    8. #include
    9. QT_BEGIN_NAMESPACE
    10. namespace Ui { class Widget; }
    11. QT_END_NAMESPACE
    12. class Widget : public QWidget
    13. {
    14. Q_OBJECT
    15. public:
    16. Widget(QWidget *parent = nullptr);
    17. ~Widget();
    18. private slots:
    19. void on_inputBtn_clicked();
    20. void on_showBtn_clicked();
    21. void on_searchBtn_clicked();
    22. void on_deleteBtn_clicked();
    23. private:
    24. Ui::Widget *ui;
    25. //定义一个数据对象
    26. QSqlDatabase db;
    27. };
    28. #endif // WIDGET_H

    .cpp

    1. #include "widget.h"
    2. #include "ui_widget.h"
    3. Widget::Widget(QWidget *parent)
    4. : QWidget(parent)
    5. , ui(new Ui::Widget)
    6. {
    7. ui->setupUi(this);
    8. //判断数据库对象是否包含了自己使用的数据库Student.db
    9. if(!db.contains("Student.db"))
    10. {
    11. //添加一个数据库
    12. //函数原型:
    13. //参数:
    14. //返回值:
    15. db = QSqlDatabase::addDatabase("QSQLITE"); //表明使用的是sqlite3版本数据库
    16. //给数据库命名
    17. db.setDatabaseName("Student.db");
    18. }
    19. //打开数据库
    20. if(!db.open())
    21. {
    22. QMessageBox::information(this,"提示","数据库打开失败");
    23. return;
    24. }
    25. //此时说明数据库已经创建出来并打开了,就可以创建数据表了
    26. //创建数据表需要使用sql语句,需要使用QSQLQuerry类对象来完成
    27. //准备sql语句
    28. QString sql = "create table if not exists myTable(" //创建表的sql语句
    29. "id integer primary key autoincrement," //id主键,允许自增
    30. "numb integer," //学号,是整形
    31. "name varchar(10)," //姓名 字符串
    32. "score integer," //分数是整形
    33. "sex varchar(4))"; //性别 字符串
    34. //定义语句执行者
    35. QSqlQuery querry;
    36. //使用querry执行sql语句
    37. if(!querry.exec(sql))
    38. {
    39. QMessageBox::information(this,"失败","创建表失败");
    40. }
    41. else
    42. {
    43. QMessageBox::information(this,"成功","创建表成功");
    44. }
    45. }
    46. Widget::~Widget()
    47. {
    48. delete ui;
    49. }
    50. //录入按钮对应的槽函数
    51. void Widget::on_inputBtn_clicked()
    52. {
    53. //获取ui界面中要存入的数据
    54. int numb_ui = ui->numbEdit->text().toInt(); //获取ui界面的学号
    55. QString name_ui = ui->nameEdit->text(); //获取ui界面的姓名
    56. int score_ui = ui->scoreEdit->text().toUInt(); //获取ui界面上的成绩
    57. QString sex_ui = ui->sexEdit->text(); //获取ui界面的性别
    58. //判断是否有漏填数据
    59. if(numb_ui == 0 || name_ui.isEmpty() || score_ui == 0 || sex_ui.isEmpty())
    60. {
    61. QMessageBox::information(this,"提示","请将信息填写完整");
    62. }
    63. //准备sql语句
    64. QString sql = QString("insert into myTable(numb,name,score,sex)"
    65. "values(%1,'%2',%3,'%4')").arg(numb_ui).arg(name_ui).arg(score_ui).arg(sex_ui);
    66. //定义语句执行
    67. QSqlQuery querry;
    68. //调用执行者的相关函数执行sql语句
    69. if(!querry.exec(sql))
    70. {
    71. QMessageBox::information(this,"失败","插入数据失败");
    72. }else
    73. {
    74. QMessageBox::information(this,"成功","插入数据成功");
    75. }
    76. }
    77. //展示按钮对应的槽函数
    78. void Widget::on_showBtn_clicked()
    79. {
    80. //准备sql语句
    81. QString sql = "select * from myTable";
    82. //准备语句执行者
    83. QSqlQuery querry;
    84. //执行sql语句
    85. if(!querry.exec(sql))
    86. {
    87. QMessageBox::information(this,"失败","查询失败");
    88. return;
    89. }
    90. //此时,将查找到的所有结果,全部放在querry对象中了
    91. //可以通过next函数不断遍历查询结果
    92. int i = 0; //记录行号
    93. while(querry.next())
    94. {
    95. //此时,遍历的就是任意一组记录:querry.record
    96. //qDebug() << querry.record();
    97. //要找到每条,记录中的每个数据使用querry.record().value(i)
    98. //qDebug() << querry.record().value(2);
    99. //querry.record().count() //返回当前记录对应数据项的个数
    100. //querry.record().value(2).toString(); //将记录的某一项的数据转变成字符串
    101. //将数据库中的表格展示到ui界面
    102. //ui->tableWidget->setItem()
    103. for(int j = 0; j < querry.record().count()-1; j++)
    104. {
    105. ui->tableWidget->setItem(i,j,new QTableWidgetItem(querry.record().value(j+1).toString()));
    106. }
    107. i++; //进行下一行
    108. }
    109. }
    110. //查找按钮对应的槽函数
    111. void Widget::on_searchBtn_clicked()
    112. {
    113. //准备sql语句
    114. QString sql = "select * from myTable where numb = 1001";
    115. //准备语句执行者
    116. QSqlQuery querry;
    117. //执行sql语句
    118. if(!querry.exec(sql))
    119. {
    120. QMessageBox::information(this,"失败","查询失败");
    121. }else
    122. {
    123. QMessageBox::information(this,"成功","查询成功");
    124. }
    125. }
    126. //删除按钮对应的槽函数
    127. void Widget::on_deleteBtn_clicked()
    128. {
    129. //准备sql语句
    130. // QString sql = "delete from myTable where name = 'damei'"; //删除某一个
    131. QString sql = "delete from myTable"; //全部删除
    132. //准备语句执行者
    133. QSqlQuery querry;
    134. //执行sql语句
    135. if(!querry.exec(sql))
    136. {
    137. QMessageBox::information(this,"删除","删除失败");
    138. }else
    139. {
    140. QMessageBox::information(this,"删除","删除成功");
    141. }
    142. }

    ui

    二.TCP通信

    server

    1. QT += core gui network
    2. greaterThan(QT_MAJOR_VERSION, 4): QT += widgets
    3. CONFIG += c++11
    4. # The following define makes your compiler emit warnings if you use
    5. # any Qt feature that has been marked deprecated (the exact warnings
    6. # depend on your compiler). Please consult the documentation of the
    7. # deprecated API in order to know how to port your code away from it.
    8. DEFINES += QT_DEPRECATED_WARNINGS
    1. #ifndef WIDGET_H
    2. #define WIDGET_H
    3. #include
    4. #include //服务器头文件
    5. #include //客户端头文件
    6. #include //链表头文件,用来存放客户端容器
    7. #include
    8. #include //消息对话框类
    9. QT_BEGIN_NAMESPACE
    10. namespace Ui { class Widget; }
    11. QT_END_NAMESPACE
    12. class Widget : public QWidget
    13. {
    14. Q_OBJECT
    15. public:
    16. Widget(QWidget *parent = nullptr);
    17. ~Widget();
    18. private slots:
    19. void on_strartBtn_clicked();
    20. void newConnection_slot(); //每当有一个新的客户端发送信号进行连接时,则进入该槽函数处理相关逻辑
    21. //如果该套接字有数据项服务器发送过来,那么该套接字就会自动发射一个readyRead信号
    22. //我们可以将该信号连接到自定义的槽函数中处理相关逻辑
    23. void readyRead_slot(); //
    24. private:
    25. Ui::Widget *ui;
    26. //1.定义服务器指针
    27. QTcpServer *server;
    28. //4.定义客户端指针链表容器
    29. QListclientList;
    30. };
    31. #endif // WIDGET_H
    1. #include "widget.h"
    2. #include "ui_widget.h"
    3. Widget::Widget(QWidget *parent)
    4. : QWidget(parent)
    5. , ui(new Ui::Widget)
    6. {
    7. ui->setupUi(this);
    8. //1.给服务器实例化一个对象
    9. server = new QTcpServer(this); //此时创建服务器成功
    10. }
    11. Widget::~Widget()
    12. {
    13. delete ui;
    14. }
    15. //2.启动按钮对应的槽函数,只有点击启动按钮后,才可以发射一个信号将服务器设置为监听状态
    16. void Widget::on_strartBtn_clicked()
    17. {
    18. //获取ui界面上的端口号,在监听前后设置都可以
    19. quint16 port = ui->portEdit->text().toInt(); //toInt 是将里面的文本转换为整型
    20. //将服务器设置为监听状态
    21. //bool QTcpServer::listen(const QHostAddress &address = QHostAddress::Any, quint16 port = 0)
    22. //参数一:要监听的主机地址,如果是any,表示监听所有主机地址,也可以给定特定的主机地址进行监听
    23. //参数二:通过指定的端口号进行访问服务器,如果是0,则表示由服务器自动分配,如果非0,则表示指定端口号
    24. //返回值:成功返回真,失败返回假
    25. if(!server->listen(QHostAddress::Any,port))
    26. {
    27. QMessageBox::critical(this,"失败","服务器启动失败");
    28. return;
    29. }else
    30. {
    31. QMessageBox::information(this,"成功","服务器启动成功");
    32. }
    33. //此时表明服务器启动成功,并对客户端连接进行监听
    34. //如果有客户端向服务器发来连接请求,那么该服务器就会自动发射一个newConnection的信号
    35. //我们可以将该信号连接到对应的槽函数中处理相关逻辑
    36. //3.进行服务器客户端连接,每当新的客户端发送过来一个连接信号,则进行一次连接
    37. //如果写在构造函数中只会连接一次所以不能写在构造函数中,要写在自定义的槽函数中
    38. connect(server,&QTcpServer::newConnection,this,&Widget::newConnection_slot);
    39. }
    40. //4.处理newConnection信号的槽函数实现
    41. void Widget::newConnection_slot()
    42. {
    43. qDebug() << "有新的客户端发来连接请求了";
    44. //4.获取最新连接的客户端的套接字
    45. //函数原型:[virtual] QTcpSocket *QTcpServer::nextPendingConnection()
    46. //参数:无
    47. //返回值:最新连接客户端套接字指针
    48. QTcpSocket *s = server->nextPendingConnection();
    49. //4.将获取的套接字存放到客户端容器中
    50. clientList.push_back(s); //进行尾插
    51. //5.此时,服务器已经和客户端建立连接请求了
    52. //如果有客户端向服务器发来数据,那么对于的客户端套接字就会发射一个readyRead的信号
    53. //我们可以将该信号连接到自定义的槽函数中处理相关逻辑
    54. connect(s,&QTcpSocket::readyRead,this,&Widget::readyRead_slot);
    55. }
    56. void Widget::readyRead_slot()
    57. {
    58. //6.进行循环遍历删除客户端链表中的无效客户端套接字
    59. for(int i = 0;i<clientList.count();i++)
    60. {
    61. //判断套接字状态
    62. //函数原型:SocketState state() const;
    63. //功能:返回客户端套接字的状态
    64. //参数:无
    65. //返回值:客户端的状态,如果结果为0,表示未连接
    66. if(clientList[i]->state() == 0)
    67. {
    68. clientList.removeAt(i); //将下标为i的客户端移除掉
    69. }
    70. }
    71. //7.循环遍历所有客户端,查看是哪个客户端发来的数据
    72. for(int i = 0;i<clientList.count();i++)
    73. {
    74. //函数原型:qint64 bytesAvailable() const override;
    75. //功能:返回当前客户端套接字中的可读数据字节个数
    76. //参数:无
    77. //返回值:当前客户端待读的字节数,如果该数据为0,表示无待读数据
    78. if(clientList[i]->bytesAvailable()!=0)
    79. {
    80. //读取当前客户端的相关数据
    81. //函数原型:QByteArray readAll();
    82. //功能:读取当前套接字中的所有数据,并返回一个字节数组
    83. //参数:无
    84. //返回值:数据的字节数组
    85. QByteArray msg = clientList[i]->readAll();
    86. //将数据展示到ui界面上
    87. //把本机字符串转换为Qstring类型的字符串
    88. ui->msgList->addItem(QString::fromLocal8Bit(msg));
    89. //将接收到的该消息,发送给所有客户端
    90. for(int j = 0;j<clientList.count();j++)
    91. {
    92. clientList[j]->write(msg);
    93. }
    94. }
    95. }
    96. }

    cli

    1. QT += core gui network
    2. greaterThan(QT_MAJOR_VERSION, 4): QT += widgets
    3. CONFIG += c++11
    4. # The following define makes your compiler emit warnings if you use
    5. # any Qt feature that has been marked deprecated (the exact warnings
    6. # depend on your compiler). Please consult the documentation of the
    7. # deprecated API in order to know how to port your code away from it.
    8. DEFINES += QT_DEPRECATED_WARNINGS
    1. #ifndef WIDGET_H
    2. #define WIDGET_H
    3. #include
    4. #include //客户端头文件
    5. #include //消息对话框类
    6. QT_BEGIN_NAMESPACE
    7. namespace Ui { class Widget; }
    8. QT_END_NAMESPACE
    9. class Widget : public QWidget
    10. {
    11. Q_OBJECT
    12. public:
    13. Widget(QWidget *parent = nullptr);
    14. ~Widget();
    15. private slots:
    16. void readyRead_slot();
    17. void connected_slot();
    18. void on_sendBtn_clicked();
    19. void on_connectBtn_clicked();
    20. void on_disconnectBtn_clicked();
    21. void disconnected_slot();
    22. private:
    23. Ui::Widget *ui;
    24. //定义一个客户端指针
    25. QTcpSocket *socket;
    26. //用户名
    27. QString userName;
    28. };
    29. #endif // WIDGET_H
    1. #include "widget.h"
    2. #include "ui_widget.h"
    3. Widget::Widget(QWidget *parent)
    4. : QWidget(parent)
    5. , ui(new Ui::Widget)
    6. {
    7. ui->setupUi(this);
    8. //给客户端指针实例化空间
    9. socket = new QTcpSocket(this);
    10. //如果连接服务器成功,该客户端就会发射一个connected的信号,
    11. //我们可以将该信号连接到自定义的槽函数中处理相关逻辑
    12. //由于该连接只需连接一次,所以,写在构造函数中即可
    13. connect(socket, &QTcpSocket::connected, this, &Widget::connected_slot);
    14. //客户端与服务器连接成功后,如果服务器向客户端发来数据,那么该客户端就会自动发射一个readyRead信号
    15. //我们可以将该信号连接到自定义的槽函数中处理相关逻辑
    16. connect(socket, &QTcpSocket::readyRead, this, &Widget::readyRead_slot);
    17. //当客户端与服务器断开连接后,该客户端就会自动发射一个disconnected的信号
    18. //我们可以将该信号与自定义的槽函数连接
    19. //由于只需要连接一次,所以将该连接写到构造函数中即可
    20. connect(socket, &QTcpSocket::disconnected, this, &Widget::disconnected_slot);
    21. }
    22. Widget::~Widget()
    23. {
    24. delete ui;
    25. }
    26. void Widget::on_connectBtn_clicked()
    27. {
    28. //获取ui界面的信息
    29. userName = ui->userNameEdit->text(); //获取用户名
    30. QString hostName = ui->ipEdit->text(); //获取主机地址
    31. quint16 port = ui->portEdit->text().toUInt(); //获取端口号
    32. //调用函数连接到主机
    33. //函数原型:[virtual] void QAbstractSocket::connectToHost(const QString &hostName, quint16 port)
    34. //参数1:服务器的主机地址
    35. //参数2:端口号
    36. //返回值:无
    37. socket->connectToHost(hostName, port);
    38. //如果连接服务器成功,该客户端就会发射一个connected的信号,
    39. //我们可以将该信号连接到自定义的槽函数中处理相关逻辑
    40. //由于该连接只需连接一次,所以,写在构造函数中即可
    41. }
    42. //关于处理connected信号的槽函数的定义
    43. void Widget::connected_slot()
    44. {
    45. QMessageBox::information(this, "成功", "连接服务器成功");
    46. //顺便向服务器发送一条消息,说:***:进入聊天室
    47. QString msg = userName + ": 进入聊天室";
    48. socket->write(msg.toLocal8Bit());
    49. }
    50. //关于readyRead信号对应槽函数的实现
    51. void Widget::readyRead_slot()
    52. {
    53. //读取该客户端中的数据
    54. QByteArray msg = socket->readAll();
    55. //将数据展示在ui界面
    56. ui->msgList->addItem(QString::fromLocal8Bit(msg));
    57. }
    58. //发送按钮对应的槽函数
    59. void Widget::on_sendBtn_clicked()
    60. {
    61. //获取UI界面中的编辑的文本内容
    62. QString m = ui->msgEdit->text();
    63. //整合要发送的信息
    64. QString msg = userName + ": " + m;
    65. //将消息发送给服务器
    66. socket->write(msg.toLocal8Bit());
    67. //将消息编辑框中的内容清空
    68. ui->msgEdit->clear();
    69. }
    70. //断开服务器按钮对应的槽函数
    71. void Widget::on_disconnectBtn_clicked()
    72. {
    73. //准备要发送的信息
    74. QString msg = userName +": 离开聊天室";
    75. socket->write(msg.toLocal8Bit());
    76. //调用成员函数disconnectFromHost
    77. //函数原型:virtual void disconnectFromHost();
    78. //功能:断开客户端与服务器的连接
    79. //参数:无
    80. //返回值:无
    81. socket->disconnectFromHost();
    82. //当客户端与服务器断开连接后,该客户端就会自动发射一个disconnected的信号
    83. //我们可以将该信号与自定义的槽函数连接
    84. //由于只需要连接一次,所以将该连接写到构造函数中即可
    85. }
    86. //disconnected信号对应槽函数的实现
    87. void Widget::disconnected_slot()
    88. {
    89. QMessageBox::information(this, "退出", "断开成功");
    90. }

  • 相关阅读:
    广度优先搜索BFS:图与迷宫
    Spring Boot Actuator的常见Endpoint
    使用ipmitool配置X86服务器的BMC网络和用户信息
    关于git版本管理与分支管理
    万木成林,我种了“Vue技能树”
    rust换源
    【笔记】大话设计模式15
    排序算法——归并排序以及非递归实现
    可转债市场和发行体制——市场的结构、发行方式、市场参与者与角色
    记一次ThreadLocal引发的线上故障
  • 原文地址:https://blog.csdn.net/Meng_fighting/article/details/132675975