QT day5 作业

服务器头文件

cpp 复制代码
#ifndef WIDGET_H
#define WIDGET_H

#include <QWidget>
#include <QTcpServer>   //服务器类
#include <QTcpSocket>   //客户端类
#include <QList>        //链表类
#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_start_clicked();
    void newConnect_slot();
    void readyRead_slot();
private:
    Ui::Widget *ui;

    QTcpServer *ser;                //定义服务器指针
    QList<QTcpSocket *> cliList;    //客户端容器链表
};
#endif // WIDGET_H

服务器源代码

cpp 复制代码
#include "widget.h"
#include "ui_widget.h"

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

    //给服务器指针实例化对象
    ser = new QTcpServer(this);
}

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

//启动按钮对应的槽函数
void Widget::on_start_clicked()
{
   if(ui->start->text() == "启动")
   {
       //获取ui界面上的端口号
       quint16 port = ui->port->text().toUInt();
       //启动服务器
       //将服务器设置为被动监听状态
       if(ser->listen(QHostAddress::Any,port) == true)
       {
           QMessageBox::information(this,"成功","服务器启动成功");
       }else
       {
           QMessageBox::information(this,"成功","服务器启动失败");
       }

       //当启动服务器后,如果有客户端发来的连接请求,那么服务器就会自动发射一个newConnect信号
       //我们可以将该信号,连接到对应的槽函数中处理相关逻辑
       connect(ser,&QTcpServer::newConnection,this,&Widget::newConnect_slot);

       //将文本内容改成关闭
       ui->start->setText("关闭");
   }else
   {
       //关闭服务器
       ser->close();

       //将文本内容改成启动
       ui->start->setText("启动");
   }
}

//处理newConnection信号的槽函数实现
void Widget::newConnect_slot()
{
    qDebug () << "有客户端发来连接请求了,请尽快处理";
    //获取最新链接的客户端套接字,并将最新连接的套接字地址返回
    QTcpSocket* socket = ser->nextPendingConnection();

    //将该客户端套接字放入到客户端容器中
    cliList.append(socket);

    //当有客户端向服务器发来数据时,当前这个客户端套接字就会自动发射一个readyRead信号
    //我们可以将该信号连接到对应的信号处理函数中,处理相关数据
    connect(socket,&QTcpSocket::readyRead,this,&Widget::readyRead_slot);

}

void Widget::readyRead_slot()
{
    //判断客户端容器汇中,是否有已经退出的客户端,或者无效的客户端,如果有将其移除
    for(int i = 0;i<cliList.length();i++)
    {
        if(cliList[i]->state() == QTcpSocket::UnconnectedState)
        {
            //功能:判断当前套接字状态
            //参数:无
            //返回值:readyRead_slot表示无效的套接字
            cliList.removeAt(i);    //将下标为i的客户端套接字从容器中移除
        }
    }

    //再将客户端容器遍历一遍,判断哪个客户端中有数据待读
    for(int i = 0;i<cliList.length();i++)
    {
        //功能:获取当前套接字中待读取数据的个数
        //参数:无
        //返回值:返回套接字中待读取数据的个数,如果为0,表示没有数据可读
        //如果不等于0,表示有数据可读,可以使用readAll读取数据
        QByteArray msg = cliList[i]->readAll();

        //将该信息,展示到ui界面上
        ui->msg->addItem(msg);

        //将该消息转发到所有客户端
        for(int j = 0;j<cliList.length();j++)
        {
            if(i != j)
            {
                cliList[j]->write(msg);
            }
        }
    }
}

客户端头文件

cpp 复制代码
#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 on_connectBtn_clicked();
    void connected_slot();
    void on_sendBtn_clicked();
    void readyRead_slot();
    void disconnectes_slot();

private:
    Ui::Widget *ui;

    QTcpSocket *cli;
    QString username;
};
#endif // WIDGET_H

客户端源文件

cpp 复制代码
#include "widget.h"
#include "ui_widget.h"

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

    //实例化一个客户端对象
    cli = new QTcpSocket(this);

    //将客户端的connected信号连接到自定义的槽函数中
    connect(cli,&QTcpSocket::connected,this,&Widget::connected_slot);
}

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

//连接服务器按钮对应的槽函数
void Widget::on_connectBtn_clicked()
{
    if(ui->connectBtn->text() == "连接服务器")
    {
        //执行连接服务器的工作
        //获取ui界面上的数据
        username = ui->userEdit->text();
        QString ip = ui->ipEdit->text();
        quint16 port = ui->portEdit->text().toUInt();

        //向服务器发送连接请求
        cli->connectToHost(ip,port);
        //功能:向指定的服务器发送连接请求
        //参数1:服务器ip地址
        //参数2:服务器端口号

        //当成功连接到服务器后,当前客户端会自动发射一个connected信号,我们可以将该信号连接到服务器
        //由于该操作只需进行一次即可,所以写在构造函数中即可

        //将按钮内容更改为断开服务器
        ui->connectBtn->setText("断开服务器");
    }else
    {
        //执行断开服务器工作
        //将按钮内容更改成连接服务器
        ui->connectBtn->setText("连接服务器");
    }
}

//自定义处理connected信号的槽函数的实现
void Widget::connected_slot()
{
    QMessageBox::information(this,"连接","连接服务器成功");
}

//信息发送按钮对应的槽函数
void Widget::on_sendBtn_clicked()
{
    //将ui界面上的文本信息获取下来
    QString msg = username + ":" + ui->msgEdit->text();
    //将该消息发送给服务器
    cli->write(msg.toLocal8Bit());
    //清空行编辑器中的内容
    ui->msgEdit->clear();
    //将消息放入ui界面中
    QListWidgetItem *item = new QListWidgetItem(msg);
    item->setTextAlignment(Qt::AlignRight);
    ui->listWidget->addItem(item);
}

//处理readyRead信号对应的槽函数的实现
void Widget::readyRead_slot()
{
    //将客户端套接字中的消息读取出来
    QByteArray msg = cli->readAll();
    //将该消息展示到ui界面
    ui->listWidget->addItem(QString::fromLocal8Bit(msg));
}

//disconnected信号对应的槽函数
void Widget::disconnectes_slot()
{
    QMessageBox::information(this,"断开","断开服务器成功");
}

sql头文件

cpp 复制代码
#ifndef WIDGET_H
#define WIDGET_H

#include <QWidget>
#include <QSqlDatabase> //数据库管理类
#include <QSqlQuery>    //数据库查询类
#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_addBtn_clicked();

    void on_searchBtn_clicked();

private:
    Ui::Widget *ui;

    //实例化一个数据库操作对象
    QSqlDatabase db;
};
#endif // WIDGET_H

sql源文件

cpp 复制代码
#include "widget.h"
#include "ui_widget.h"

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


    //判断当前数据库操作对象中,是否包含了要处理的数据库
    if(!db.contains("mydb.db"))
    {
        //添加一个数据库到当前的数据库对象中
        db = QSqlDatabase::addDatabase("QSQLITE");  //表示使用的是sqlite3数据库
        //给数据库设置名字
        db.setDatabaseName("mydb.db");
    }

    //此时已经创建了该数据库但是还没有打开
    if(!db.open())
    {
        QMessageBox::information(this,"失败","数据库打开失败");
        return;
    }

    //程序执行至此,说明数据库打开成功
    //准备sql语句
    QString sql = "create table if not exists Stu(name char,numb int,sex char,score double)";
    //实例化一个sql语句的执行者
    QSqlQuery query;
    if(!query.exec(sql))
    {
        QMessageBox::information(this,"提示","创建数据表失败");
        return;
    }
}

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

//添加学员信息按钮对应的槽函数
void Widget::on_addBtn_clicked()
{
    //将ui界面上的相关信息获取下来
    QString ui_name = ui->nameEdit->text();
    int ui_number = ui->numberEdit->text().toUInt();
    QString ui_sex = ui->sexEdit->text();
    double ui_score = ui->scoreEdit->text().toDouble();

    //判断是否有空的没有填写的数据
    if(ui_name == NULL || ui_number == 0 || ui_sex == NULL || ui_score == 0)
    {
        QMessageBox::information(this,"提示","有内容没有填写");
        return;
    }

    //准备sql语句
    QString sql = QString("insert into Stu values('%1',%2,'%3',%4)")
            .arg(ui_name).arg(ui_number).arg(ui_sex).arg(ui_score);
    //实例化一个sql语句的执行者
    QSqlQuery query;
    if(!query.exec(sql))
    {
        QMessageBox::information(this,"提示","添加数据失败");
        return;
    }else
    {
        QMessageBox::information(this,"提示","添加数据成功");
        return;
    }
}

//查找按钮对应的槽函数
void Widget::on_searchBtn_clicked()
{
    QString sql;
    //准备sql语句
    if(ui->nameEdit->text() == NULL)
    {
        sql = "select * from Stu";
    }else
    {
        sql = QString("select '%1' from Stu").arg(ui->nameEdit->text());
    }

    //执行sql语句
    //实例化一个sql语句的执行者
    QSqlQuery query;
    if(!query.exec(sql))
    {
        QMessageBox::information(this,"提示","查询数据失败");
        return;
    }

    //将查询结果展示到ui界面上
    int i = 0;
    while(query.next())
    {
        //这里面是一个任意的查询结果,query对象中保存的是当前的一个记录
        //可以通过成员函数:QSqlRecord QSqlQuery::record() const
        //通过QSqlRecord类的成员函数:count,来获取当前记录中的列数
        //通过调用QSqlRecord类的成员函数:value(i),来获取下标为i列的那一项的数据值
        for(int j = 0;j < query.record().count();j++)
        {
            qDebug() << query.record().value(j).toString();
            //将数据库中的数据,依次存放到ui界面中
            ui->tableWidget->setItem(i, j, new QTableWidgetItem(query.record().value(j).toString()));
        }
        i++;
    }
}

思维导图

相关推荐
落落落sss6 分钟前
MybatisPlus
android·java·开发语言·spring·tomcat·rabbitmq·mybatis
简单.is.good24 分钟前
【测试】接口测试与接口自动化
开发语言·python
Yvemil743 分钟前
MQ 架构设计原理与消息中间件详解(二)
开发语言·后端·ruby
程序员是干活的1 小时前
私家车开车回家过节会发生什么事情
java·开发语言·软件构建·1024程序员节
我是陈泽1 小时前
一行 Python 代码能实现什么丧心病狂的功能?圣诞树源代码
开发语言·python·程序员·编程·python教程·python学习·python教学
优雅的小武先生1 小时前
QT中的按钮控件和comboBox控件和spinBox控件无法点击的bug
开发语言·qt·bug
Death2001 小时前
使用Qt进行TCP和UDP网络编程
网络·c++·qt·tcp/ip
虽千万人 吾往矣1 小时前
golang gorm
开发语言·数据库·后端·tcp/ip·golang
创作小达人1 小时前
家政服务|基于springBoot的家政服务平台设计与实现(附项目源码+论文+数据库)
开发语言·python
郭二哈1 小时前
C++——list
开发语言·c++·list