QT 第五天 TCP通信与数据库

news2025/2/24 23:29:40

一、数据库增删改查

QT       += core gui sql

greaterThan(QT_MAJOR_VERSION, 4): QT += widgets

CONFIG += c++11

# The following define makes your compiler emit warnings if you use
# any Qt feature that has been marked deprecated (the exact warnings
# depend on your compiler). Please consult the documentation of the
# deprecated API in order to know how to port your code away from it.

.h

#ifndef WIDGET_H
#define WIDGET_H

#include <QWidget>
#include <QSqlDatabase>   //数据库管理类
#include <QSqlQuery>      //执行sql语句对应的类
#include <QSqlRecord>     //纪录类
#include <QMessageBox>
#include <QDebug>

QT_BEGIN_NAMESPACE
namespace Ui { class Widget; }
QT_END_NAMESPACE

class Widget : public QWidget
{
    Q_OBJECT

public:
    Widget(QWidget *parent = nullptr);
    ~Widget();

private slots:
    void on_inputBtn_clicked();

    void on_showBtn_clicked();

    void on_searchBtn_clicked();

    void on_deleteBtn_clicked();

private:
    Ui::Widget *ui;

    //定义一个数据对象
    QSqlDatabase db;
};
#endif // WIDGET_H

.cpp

#include "widget.h"
#include "ui_widget.h"

Widget::Widget(QWidget *parent)
    : QWidget(parent)
    , ui(new Ui::Widget)
{
    ui->setupUi(this);

    //判断数据库对象是否包含了自己使用的数据库Student.db
    if(!db.contains("Student.db"))
    {
        //添加一个数据库
        //函数原型:
        //参数:
        //返回值:
        db = QSqlDatabase::addDatabase("QSQLITE"); //表明使用的是sqlite3版本数据库

        //给数据库命名
        db.setDatabaseName("Student.db");
    }

    //打开数据库
    if(!db.open())
    {
        QMessageBox::information(this,"提示","数据库打开失败");
        return;
    }

    //此时说明数据库已经创建出来并打开了,就可以创建数据表了
    //创建数据表需要使用sql语句,需要使用QSQLQuerry类对象来完成
    //准备sql语句
    QString sql = "create table if not exists myTable("              //创建表的sql语句
                     "id integer primary key autoincrement,"          //id主键,允许自增
                     "numb integer,"                                   //学号,是整形
                     "name varchar(10),"                               //姓名   字符串
                     "score integer,"                                  //分数是整形
                     "sex varchar(4))";                                 //性别 字符串

    //定义语句执行者
    QSqlQuery querry;

    //使用querry执行sql语句
    if(!querry.exec(sql))
    {
        QMessageBox::information(this,"失败","创建表失败");
    }
    else
    {
         QMessageBox::information(this,"成功","创建表成功");
    }
}

Widget::~Widget()
{
    delete ui;
}

//录入按钮对应的槽函数
void Widget::on_inputBtn_clicked()
{
    //获取ui界面中要存入的数据
    int numb_ui = ui->numbEdit->text().toInt();   //获取ui界面的学号
    QString name_ui = ui->nameEdit->text();       //获取ui界面的姓名
    int score_ui = ui->scoreEdit->text().toUInt();  //获取ui界面上的成绩
    QString sex_ui = ui->sexEdit->text();          //获取ui界面的性别

    //判断是否有漏填数据
    if(numb_ui == 0 || name_ui.isEmpty() || score_ui == 0 || sex_ui.isEmpty())
    {
        QMessageBox::information(this,"提示","请将信息填写完整");
    }

    //准备sql语句
    QString sql = QString("insert into myTable(numb,name,score,sex)"
                  "values(%1,'%2',%3,'%4')").arg(numb_ui).arg(name_ui).arg(score_ui).arg(sex_ui);

    //定义语句执行
    QSqlQuery querry;

    //调用执行者的相关函数执行sql语句
    if(!querry.exec(sql))
    {
        QMessageBox::information(this,"失败","插入数据失败");
    }else
    {
        QMessageBox::information(this,"成功","插入数据成功");
    }
}
//展示按钮对应的槽函数
void Widget::on_showBtn_clicked()
{
    //准备sql语句
    QString sql = "select * from myTable";

    //准备语句执行者
    QSqlQuery querry;

    //执行sql语句
    if(!querry.exec(sql))
    {
        QMessageBox::information(this,"失败","查询失败");
        return;

    }

    //此时,将查找到的所有结果,全部放在querry对象中了
    //可以通过next函数不断遍历查询结果
    int i = 0;   //记录行号
    while(querry.next())
    {
        //此时,遍历的就是任意一组记录:querry.record
        //qDebug() << querry.record();
        //要找到每条,记录中的每个数据使用querry.record().value(i)
        //qDebug() << querry.record().value(2);
        //querry.record().count()  //返回当前记录对应数据项的个数
        //querry.record().value(2).toString();  //将记录的某一项的数据转变成字符串

        //将数据库中的表格展示到ui界面
        //ui->tableWidget->setItem()

        for(int j = 0; j < querry.record().count()-1; j++)
        {
            ui->tableWidget->setItem(i,j,new QTableWidgetItem(querry.record().value(j+1).toString()));
        }
           i++;  //进行下一行
    }
}
//查找按钮对应的槽函数
void Widget::on_searchBtn_clicked()
{
    //准备sql语句
    QString sql = "select * from myTable where numb = 1001";
    //准备语句执行者
    QSqlQuery querry;

    //执行sql语句
    if(!querry.exec(sql))
    {
        QMessageBox::information(this,"失败","查询失败");
    }else
    {
        QMessageBox::information(this,"成功","查询成功");
    }

}
//删除按钮对应的槽函数
void Widget::on_deleteBtn_clicked()
{
    //准备sql语句
  //  QString sql = "delete from myTable where name = 'damei'";  //删除某一个
    QString sql = "delete from myTable";   //全部删除

    //准备语句执行者
    QSqlQuery querry;

    //执行sql语句
    if(!querry.exec(sql))
    {
        QMessageBox::information(this,"删除","删除失败");
    }else
    {
        QMessageBox::information(this,"删除","删除成功");
    }


}

ui

二.TCP通信

server

QT       += core gui network

greaterThan(QT_MAJOR_VERSION, 4): QT += widgets

CONFIG += c++11

# The following define makes your compiler emit warnings if you use
# any Qt feature that has been marked deprecated (the exact warnings
# depend on your compiler). Please consult the documentation of the
# deprecated API in order to know how to port your code away from it.
DEFINES += QT_DEPRECATED_WARNINGS
#ifndef WIDGET_H
#define WIDGET_H

#include <QWidget>
#include <QTcpServer>  //服务器头文件
#include <QTcpSocket>  //客户端头文件
#include <QList>       //链表头文件,用来存放客户端容器
#include <QDebug>
#include <QMessageBox> //消息对话框类

QT_BEGIN_NAMESPACE
namespace Ui { class Widget; }
QT_END_NAMESPACE

class Widget : public QWidget
{
    Q_OBJECT

public:
    Widget(QWidget *parent = nullptr);
    ~Widget();

private slots:
    void on_strartBtn_clicked();

    void newConnection_slot();  //每当有一个新的客户端发送信号进行连接时,则进入该槽函数处理相关逻辑

    //如果该套接字有数据项服务器发送过来,那么该套接字就会自动发射一个readyRead信号
    //我们可以将该信号连接到自定义的槽函数中处理相关逻辑
    void readyRead_slot();     //

private:
    Ui::Widget *ui;

    //1.定义服务器指针
    QTcpServer *server;

    //4.定义客户端指针链表容器
    QList<QTcpSocket *>clientList;


};
#endif // WIDGET_H
#include "widget.h"
#include "ui_widget.h"

Widget::Widget(QWidget *parent)
    : QWidget(parent)
    , ui(new Ui::Widget)
{
    ui->setupUi(this);

    //1.给服务器实例化一个对象
    server = new QTcpServer(this);  //此时创建服务器成功
}

Widget::~Widget()
{
    delete ui;
}

//2.启动按钮对应的槽函数,只有点击启动按钮后,才可以发射一个信号将服务器设置为监听状态
void Widget::on_strartBtn_clicked()
{
    //获取ui界面上的端口号,在监听前后设置都可以
    quint16 port = ui->portEdit->text().toInt();  //toInt 是将里面的文本转换为整型

    //将服务器设置为监听状态
    //bool QTcpServer::listen(const QHostAddress &address = QHostAddress::Any, quint16 port = 0)
    //参数一:要监听的主机地址,如果是any,表示监听所有主机地址,也可以给定特定的主机地址进行监听
    //参数二:通过指定的端口号进行访问服务器,如果是0,则表示由服务器自动分配,如果非0,则表示指定端口号
    //返回值:成功返回真,失败返回假
    if(!server->listen(QHostAddress::Any,port))
    {
        QMessageBox::critical(this,"失败","服务器启动失败");
        return;
    }else
    {
        QMessageBox::information(this,"成功","服务器启动成功");
    }

    //此时表明服务器启动成功,并对客户端连接进行监听
    //如果有客户端向服务器发来连接请求,那么该服务器就会自动发射一个newConnection的信号
    //我们可以将该信号连接到对应的槽函数中处理相关逻辑
    //3.进行服务器客户端连接,每当新的客户端发送过来一个连接信号,则进行一次连接
    //如果写在构造函数中只会连接一次所以不能写在构造函数中,要写在自定义的槽函数中
    connect(server,&QTcpServer::newConnection,this,&Widget::newConnection_slot);

}
//4.处理newConnection信号的槽函数实现
void Widget::newConnection_slot()
{
    qDebug() << "有新的客户端发来连接请求了";

    //4.获取最新连接的客户端的套接字
    //函数原型:[virtual] QTcpSocket *QTcpServer::nextPendingConnection()
    //参数:无
    //返回值:最新连接客户端套接字指针
    QTcpSocket *s = server->nextPendingConnection();

    //4.将获取的套接字存放到客户端容器中
    clientList.push_back(s);   //进行尾插


    //5.此时,服务器已经和客户端建立连接请求了
    //如果有客户端向服务器发来数据,那么对于的客户端套接字就会发射一个readyRead的信号
    //我们可以将该信号连接到自定义的槽函数中处理相关逻辑
    connect(s,&QTcpSocket::readyRead,this,&Widget::readyRead_slot);
}
void Widget::readyRead_slot()
{
    //6.进行循环遍历删除客户端链表中的无效客户端套接字
    for(int i = 0;i<clientList.count();i++)
    {
        //判断套接字状态
        //函数原型:SocketState state() const;
        //功能:返回客户端套接字的状态
        //参数:无
        //返回值:客户端的状态,如果结果为0,表示未连接
        if(clientList[i]->state() == 0)
        {
            clientList.removeAt(i);   //将下标为i的客户端移除掉
        }
    }

    //7.循环遍历所有客户端,查看是哪个客户端发来的数据
    for(int i = 0;i<clientList.count();i++)
    {
        //函数原型:qint64 bytesAvailable() const override;
        //功能:返回当前客户端套接字中的可读数据字节个数
        //参数:无
        //返回值:当前客户端待读的字节数,如果该数据为0,表示无待读数据
        if(clientList[i]->bytesAvailable()!=0)
        {
            //读取当前客户端的相关数据
            //函数原型:QByteArray readAll();
            //功能:读取当前套接字中的所有数据,并返回一个字节数组
            //参数:无
            //返回值:数据的字节数组
            QByteArray msg = clientList[i]->readAll();

            //将数据展示到ui界面上
            //把本机字符串转换为Qstring类型的字符串
            ui->msgList->addItem(QString::fromLocal8Bit(msg));

            //将接收到的该消息,发送给所有客户端
            for(int j = 0;j<clientList.count();j++)
            {
                clientList[j]->write(msg);
            }
        }
    }
}

cli

QT       += core gui network

greaterThan(QT_MAJOR_VERSION, 4): QT += widgets

CONFIG += c++11

# The following define makes your compiler emit warnings if you use
# any Qt feature that has been marked deprecated (the exact warnings
# depend on your compiler). Please consult the documentation of the
# deprecated API in order to know how to port your code away from it.
DEFINES += QT_DEPRECATED_WARNINGS

#ifndef WIDGET_H
#define WIDGET_H

#include <QWidget>
#include <QTcpSocket>   //客户端头文件
#include <QMessageBox>  //消息对话框类

QT_BEGIN_NAMESPACE
namespace Ui { class Widget; }
QT_END_NAMESPACE

class Widget : public QWidget
{
    Q_OBJECT

public:
    Widget(QWidget *parent = nullptr);
    ~Widget();

private slots:
    void readyRead_slot();

    void connected_slot();

    void on_sendBtn_clicked();

    void on_connectBtn_clicked();

    void on_disconnectBtn_clicked();

    void disconnected_slot();

private:
    Ui::Widget *ui;

    //定义一个客户端指针
    QTcpSocket *socket;


    //用户名
    QString userName;
};
#endif // WIDGET_H
#include "widget.h"
#include "ui_widget.h"

Widget::Widget(QWidget *parent)
    : QWidget(parent)
    , ui(new Ui::Widget)
{
    ui->setupUi(this);

    //给客户端指针实例化空间
    socket = new QTcpSocket(this);

    //如果连接服务器成功,该客户端就会发射一个connected的信号,
    //我们可以将该信号连接到自定义的槽函数中处理相关逻辑
    //由于该连接只需连接一次,所以,写在构造函数中即可
    connect(socket, &QTcpSocket::connected, this, &Widget::connected_slot);

    //客户端与服务器连接成功后,如果服务器向客户端发来数据,那么该客户端就会自动发射一个readyRead信号
    //我们可以将该信号连接到自定义的槽函数中处理相关逻辑
    connect(socket, &QTcpSocket::readyRead, this, &Widget::readyRead_slot);

    //当客户端与服务器断开连接后,该客户端就会自动发射一个disconnected的信号
    //我们可以将该信号与自定义的槽函数连接
    //由于只需要连接一次,所以将该连接写到构造函数中即可
    connect(socket, &QTcpSocket::disconnected, this, &Widget::disconnected_slot);
}

Widget::~Widget()
{
    delete ui;
}


void Widget::on_connectBtn_clicked()
{
    //获取ui界面的信息
    userName = ui->userNameEdit->text();        //获取用户名
    QString hostName = ui->ipEdit->text();       //获取主机地址
    quint16 port = ui->portEdit->text().toUInt();  //获取端口号


    //调用函数连接到主机
    //函数原型:[virtual] void QAbstractSocket::connectToHost(const QString &hostName, quint16 port)
    //参数1:服务器的主机地址
    //参数2:端口号
    //返回值:无
    socket->connectToHost(hostName, port);


    //如果连接服务器成功,该客户端就会发射一个connected的信号,
    //我们可以将该信号连接到自定义的槽函数中处理相关逻辑
    //由于该连接只需连接一次,所以,写在构造函数中即可
}
//关于处理connected信号的槽函数的定义
void Widget::connected_slot()
{
    QMessageBox::information(this, "成功", "连接服务器成功");


    //顺便向服务器发送一条消息,说:***:进入聊天室
    QString msg = userName + ": 进入聊天室";


    socket->write(msg.toLocal8Bit());
}
//关于readyRead信号对应槽函数的实现
void Widget::readyRead_slot()
{
    //读取该客户端中的数据
    QByteArray msg = socket->readAll();


    //将数据展示在ui界面
    ui->msgList->addItem(QString::fromLocal8Bit(msg));
}

//发送按钮对应的槽函数
void Widget::on_sendBtn_clicked()
{
    //获取UI界面中的编辑的文本内容
    QString m = ui->msgEdit->text();


    //整合要发送的信息
    QString msg = userName + ": " + m;


    //将消息发送给服务器
    socket->write(msg.toLocal8Bit());


    //将消息编辑框中的内容清空
    ui->msgEdit->clear();
}


//断开服务器按钮对应的槽函数
void Widget::on_disconnectBtn_clicked()
{
    //准备要发送的信息
    QString msg = userName +": 离开聊天室";
    socket->write(msg.toLocal8Bit());


    //调用成员函数disconnectFromHost
    //函数原型:virtual void disconnectFromHost();
    //功能:断开客户端与服务器的连接
    //参数:无
    //返回值:无
    socket->disconnectFromHost();


    //当客户端与服务器断开连接后,该客户端就会自动发射一个disconnected的信号
    //我们可以将该信号与自定义的槽函数连接
    //由于只需要连接一次,所以将该连接写到构造函数中即可

}
//disconnected信号对应槽函数的实现
void Widget::disconnected_slot()
{
    QMessageBox::information(this, "退出", "断开成功");
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/982304.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

第4章 【MySQL】InnoDB记录结构

4.1 准备工作 MySQL 服务器上负责对表中数据的读取和写入工作的部分是 存储引擎 &#xff0c;而服务器又支持不同类型的存储引擎&#xff0c;比如 InnoDB 、 MyISAM 、 Memory 啥的&#xff0c;不同的存储引擎一般是由不同的人为实现不同的特性而开发的&#xff0c;真实数据在…

go-zerogo web集成redis实战

前言 上一篇&#xff1a;go-zero&go web集成JWT和cobra命令行工具实战 从零开始基于go-zero搭建go web项目实战-03集成redis实战 源码仓库地址 源码 https://gitee.com/li_zheng/treasure-box golang redis 客户端 Go-Redis 地址&#xff1a; GitHub: https://github.…

酒店常见十大突发事件应急处置方案

文章目录 1.处理客房门未关的程序2.客房内异常声响的处理程序3.酗酒客人应对程序4.预防打架斗殴、流氓滋事5.停电紧急处理6.客人差欠、拒付酒店费用的处理程序7.客人意外受伤、病危、身亡的处理程序8.防风、防汛等自然灾害应急处理9.发生盗窃案处理程序10.客人报告的“丢失/盗窃…

链表例题小总结:

链表&#xff1a; 第一种题型&#xff1a;双指针 力扣203&#xff1a;移除链表元素 力扣题目链接 题意&#xff1a;删除链表中等于给定值 val 的所有节点。示例 1&#xff1a; 输入&#xff1a;head [1,2,6,3,4,5,6], val 6 输出&#xff1a;[1,2,3,4,5]示例 2&#xff1…

浏览器窗口间的通信

一、汇总 二、同源策略 三、webSocket (无跨域限制) 优点&#xff1a;无跨域限制 缺点&#xff1a;成本高 四、客户端存储 1、localStorage onStorage 例子&#xff1a; 2、定时器 客户端存储 例子&#xff1a; 缺点&#xff1a; 五、postMessage &#xff08;无跨域…

TypeScript类型判断

快速认知 TS允许我们为变量设置类型限制并进行检测判断 // 常见的类型判断 let age: number 20; let isDead: boolean true; let name: string abc; 但是上面的写法太啰嗦了。ts有一个类型推断机制&#xff0c;ts会根据为变量赋的值自动给该变量设置一个类型。上面可以写为…

SpringMvc--综合案例

目录 1.SpringMvc的常用注解 2.参数传递 基础类型&#xff08;String&#xff09; 创建一个paramController类&#xff1a; 创建一个index.jsp 测试结果 复杂方式 ​编辑 测试结果 RequestParam 测试结果 PathVariable 测试结果 RequestBody pom.xml依赖导入 输…

软件测试之登录测试详解-功能性

功能测试 一、功能测试–登录 功能性测试用例包括&#xff1a; 1.什么都不输入&#xff0c;点击提交按钮&#xff0c;看提示信息。&#xff08;非空检查&#xff09; 2.输入已注册的用户名和正确的密码&#xff0c;验证是否登录成功&#xff1b; 3.输入已注册的用户名和不…

面试中的问题提问:如何通过提问展示你的主动性

&#x1f337;&#x1f341; 博主猫头虎&#xff08;&#x1f405;&#x1f43e;&#xff09;带您 Go to New World✨&#x1f341; &#x1f984; 博客首页——&#x1f405;&#x1f43e;猫头虎的博客&#x1f390; &#x1f433; 《面试题大全专栏》 &#x1f995; 文章图文…

大型语言模型,第 1 部分:BERT

一、介绍 2017是机器学习中具有历史意义的一年&#xff0c;当变形金刚模型首次出现在现场时。它在许多基准测试上都表现出色&#xff0c;并且适用于数据科学中的许多问题。由于其高效的架构&#xff0c;后来开发了许多其他基于变压器的模型&#xff0c;这些模型更专注于特定任务…

Nginx详解 五:反向代理

文章目录 1. 正向代理和反向代理1.1 正向代理概述1.1.1 什么是正向代理1.1.2 正向代理的作用1.1.3 正向代理的基本格式 1.2 反向代理概述1.2.1 什么是反向代理1.2.2 反向代理可实现的功能1.2.3 反向代理的可用模块 2. 配置反向代理2.1 反向代理配置参数2.1.1 proxy_pass2.1.2 其…

(其他) 剑指 Offer 65. 不用加减乘除做加法 ——【Leetcode每日一题】

❓ 剑指 Offer 65. 不用加减乘除做加法 难度&#xff1a;简单 写一个函数&#xff0c;求两个整数之和&#xff0c;要求在函数体内不得使用 “”、“-”、“*”、“/” 四则运算符号。 示例: 输入: a 1, b 1 输出: 2 提示&#xff1a; a, b 均可能是负数或 0结果不会溢出 …

在 Windows 上远程对 Linux 进行抓包

文章目录 名词解释事先准备下载安装 Wireshark下载运行 libpcap设置 libpcap 环境变量在 Wireshark 中远程连接 libpcap 笔者的运行环境&#xff1a;&#xff08;成功&#xff09; 本地客户端&#xff1a; Windows&#xff1a; Windows 10 教育版&#xff08;本文&#xff09; …

基于STM32设计的生理监测装置

一、项目功能要求 设计并制作一个生理监测装置&#xff0c;能够实时监测人体的心电图、呼吸和温度&#xff0c;并在LCD液晶显示屏上显示相关数据。 随着现代生活节奏的加快和环境的变化&#xff0c;人们对身体健康的关注程度越来越高。为了及时掌握自身的生理状况&#xff0c…

Hololens2部署很慢可能是unity工程选择不对

这样就很快&#xff0c;几分钟就完成了。&#xff08;虽然又遇到新问题了&#xff09; 第一次使用时如下&#xff0c;直接运行了一个多小时还没有完

虚拟专用网络——VPN

VPN的英文全称是"Virtual Private Network"&#xff0c;意为"虚拟专用网络"。它的本质是一种特殊的加密通讯协议&#xff0c;可以在不同地点的企业内部网之间建立一条专用的通讯线路&#xff0c;就像真正铺设了一条专线一样&#xff0c;但无需真正的物理线…

【图卷积神经网络】1-入门篇:为什么使用图神经网络

在本节中,将涵盖以下主要内容: 为什么使用图?为什么学习图?为什么使用图神经网络?为什么使用图? 首先需要回答的问题是:为什么对图感兴趣?图论是对图进行数学研究的学科,它已经成为理解复杂系统和关系的基本工具。图是一种将节点(也称为顶点)和连接这些节点的边的集…

go语言的高级特性

go语言调用C语言 go tool cgo main.go

MySQL误删数据 回滚

前言 生产环境数据库不允许删除表&#xff0c;可以将表修改成 XXX_to_delete 如果误删简单数据&#xff0c;可以考虑使用binlog恢复 一、查看命令 1.查看binlog是否开启 show variables like log_bin;切换到MySQL安装目录,查看mysqlbinlog日志文件 2.查看所有 binlog 日志…

网络技术学习十二:子网划分

子网划分 A类地址 ⑴ A类地址第1字节为网络地址&#xff0c;其它3个字节为主机地址。另外第1个字节的最高位固定为0。 ⑵ A类地址范围&#xff1a;1.0.0.1到126.255.255.254。 ⑶ A类地址中的私有地址和保留地址&#xff1a; ①10.0.0.0到10.255.255.255是私有地址&#xff0…