QT学习day5(QT实现TCP协议)

news2024/10/7 8:27:14

作业:利用TCP客户端和服务器实现网络聊天室(简单版QQ)

1.服务器代码

widget.h

#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_startBtn_clicked();

    void newConnection_slot();          //自定义处理newConnection信号的槽函数的声明
    void readyRead_slot();              //自定义处理readyRead信号的槽函数的声明


    
private:
    Ui::Widget *ui;
    //实例化服务对象
    QTcpServer *server;//实例化一个服务器对象
    //创一个存放客户端的套接字的容器
    QList<QTcpSocket *> clientList;
};
#endif // WIDGET_H

widget.cpp

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

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

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


    //初始化界面(设置不可用)
    ui->msgEdit->setEnabled(false);
    ui->setBtn->setEnabled(false);
    ui->disBtn->setEnabled(false);


    //判断是否连接成功,如果连接成功客户端会自动发射connected,将该信号连接到自定义的槽函数中处理相关的逻辑
    //因为只需要连接一次,所以我们将连接函数写在构造函数中
    connect(socket,&QTcpSocket::connected,this,&Widget::connected_slot);//定义在构造函数是为了只连接一次


    //此时说明服务器和客户端此时已经建立好连接,如果服务器发来数据,该客户端会自动发射readRead信号
    connect(socket,&QTcpSocket::readyRead,this,&Widget::readyRead_slot);

      //判断是否断开成功,如果成功断开连接,客户端自动发射disconnect信号
    connect(socket,&QTcpSocket::disconnected,this,&Widget::dis_slot);

}

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

//链接服务器按钮对应的槽函数
void Widget::on_connectStn_clicked()
{

    //获取ui界面上的IP和端口号
    uesrName=ui->usrnameEdit->text();
    QString ip= ui->ipEdit->text();
    quint16 port=ui->portEdit->text().toUInt();//转换成整型
    //客户端连接链接服务器
    socket->connectToHost(ip,port);




}
//连接成功对应的槽函数实现
void Widget::connected_slot()
{
    //告诉服务器 我来了
    QString msg = uesrName + ":进入聊天室";
    //将信息发送给服务器
    socket ->write(msg.toLocal8Bit());



    //将ui界面上的控价进行相关设置

    ui->usrnameEdit->setEnabled(false);
    ui->ipEdit->setEnabled(false);
    ui->portEdit->setEnabled(false);
    ui->connectStn->setEnabled(false);



    ui->msgEdit->setEnabled(true);
    ui->setBtn->setEnabled(true);
    ui->disBtn->setEnabled(true);


}
void Widget::readyRead_slot()//readyread对应的槽函数
{
    //说明服务器给客户端发来数据
    QByteArray msg = socket->readAll();
    //将数据放入到ui界面中
    ui->listWidget->addItem(QString::fromLocal8Bit(msg));

}

void Widget::dis_slot()
{
    ui->usrnameEdit->setEnabled(true);
    ui->ipEdit->setEnabled(true);
    ui->portEdit->setEnabled(true);
    ui->connectStn->setEnabled(true);



    ui->msgEdit->setEnabled(false);
    ui->setBtn->setEnabled(false);
    ui->disBtn->setEnabled(false);

}


void Widget::on_setBtn_clicked()//发送按钮对应的槽函数处理
{
    //获取ui界面上的文本内容
    QString msg =uesrName+":"+ ui->msgEdit->text();
    //将信息发送给服务器
    socket->write(msg.toLocal8Bit());

    //将msg的文本清空
    ui->msgEdit->clear();

}

void Widget::on_disBtn_clicked()//断开按钮对应的槽函数处理
{
   QString msg = uesrName+":"+ "离开了聊天室,尔等也退下吧";
   socket->write(msg.toLocal8Bit());

   socket->disconnectFromHost();


}






服务器 ui界面:

 

2.客户端代码

second.h

#ifndef SECOND_H
#define SECOND_H

#include <QWidget>
#include<QIcon>
#include<QTcpServer>//服务器头文件
#include<QTcpSocket>//客户端头文件
#include<QMessageBox>//消息对话框
#include<QDebug>//调试类


namespace Ui {
class Second;
}

class Second : public QWidget
{
    Q_OBJECT
public slots:
    void jump_slot();//接收跳转信号函数

public:
    explicit Second(QWidget *parent = nullptr);
    ~Second();

private slots:
    void on_connectBtn_clicked();//链接服务器对应的槽函数声明
    void connected_solt();
    void readyRead_slot();
    void dis_slot();

    void on_sendBtn_clicked();

    void on_disBtn_clicked();

private:
    Ui::Second *ui;
    //实例化一个客户端对象
    QTcpSocket *socket;

    //定义一个用户名的变量
    QString userName;
};

#endif // SECOND_H

 

widget.h 

 

#ifndef WIDGET_H
#define WIDGET_H

#include <QWidget>
#include<QMovie>//动态图
#include<QPixmap>//图片
#include<QDebug>//输出
#include<QPushButton>//按钮类
#include<QMessageBox>//信息类
#include<QIcon>//图片


QT_BEGIN_NAMESPACE
namespace Ui { class Widget; }
QT_END_NAMESPACE

class Widget : public QWidget
{
    Q_OBJECT

public:
    Widget(QWidget *parent = nullptr);
    ~Widget();
signals://自定义跳转信号函数
    void jump();

private slots:
    //void on_pushButton_2_clicked();
    void my_slot();//自己定义的槽函数


private:
    Ui::Widget *ui;


};
#endif // WIDGET_H

 

main.cpp

#include "widget.h"
#include"second.h"
#include <QApplication>

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
    Widget w;
    w.show();

    //实例化第二个窗口的对象
    Second s;
    QObject::connect(&w,&Widget::jump,&s,&Second::jump_slot);
    return a.exec();
}

 

second.cpp

#include "second.h"
#include "ui_second.h"

void Second::jump_slot()//跳转信号槽函数
{
    this->show();//将自己的界面进行展示
}

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

    //第二个界面的窗口设置
    this->setWindowTitle("划水摆烂群");
    this->setWindowIcon(QIcon(":/pictrue/eaeb1d87_E780070_63de2b7c.png"));

    //ui->listWidget->setStyleSheet("QListWidget { background-color: transparent; }");//设置背景为透明色


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

    //初始化界面(未连接服务器时)
    ui->msgEdit->setEnabled(false);//消息对话框不可用
    ui->sendBtn->setEnabled(false);//发送按钮不可用
    ui->disBtn->setEnabled(false);//离线不可用



    //判断是否连接成功,如果连接成功客户端会自动发射connected,将该信号连接到自定义的槽函数中处理相关的逻辑
    //因为只需要连接一次,所以我们将连接函数写在构造函数中
    connect(socket,&QTcpSocket::connected,this,&Second::connected_solt);//定义在构造函数是为了只连接一次

    //此时说明服务器和客户端此时已经建立好连接,如果服务器发来数据,该客户端会自动发射readRead信号
    connect(socket,&QTcpSocket::readyRead,this,&Second::readyRead_slot);


}


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

void Second::on_connectBtn_clicked()//链接服务器对应的槽函数
{
    //获取ui界面上的IP和端口号
    userName=ui->usernameEdit->text();//获取用户名
    QString ip=ui->ipEdit->text();//获取ip
    quint16 port=ui->portEdit_2->text().toUInt();//获取端口号
    //客户端连接服务器
    socket->connectToHost(ip,port);


}

void Second::connected_solt()//连接成功对应的槽函数
{
    //告诉服务器我上线了
    QString msg = userName + ":已上线";
    //将消息发送给服务器
    socket ->write(msg.toLocal8Bit());

    //重新设置ui界面上的控件
    ui->usernameEdit->setEnabled(false);
    ui->ipEdit->setEnabled(false);
    ui->portEdit_2->setEnabled(false);
    ui->connectBtn->setEnabled(false);



    ui->msgEdit->setEnabled(true);
    ui->sendBtn->setEnabled(true);
    ui->disBtn->setEnabled(true);



}

void Second::readyRead_slot()
{
    //说明服务器给客户端发来数据
    QByteArray msg = socket->readAll();
    //将数据放入到ui界面中
    ui->listWidget->addItem(QString::fromLocal8Bit(msg));
}

void Second::dis_slot()
{
    ui->usernameEdit->setEnabled(true);
    ui->ipEdit->setEnabled(true);
    ui->portEdit_2->setEnabled(true);
    ui->connectBtn->setEnabled(true);



    ui->msgEdit->setEnabled(false);
    ui->sendBtn->setEnabled(false);
    ui->disBtn->setEnabled(false);

}
void Second::on_sendBtn_clicked()//发送按钮对应的槽函数
{
    //获取ui界面上的文本内容
    QString msg =userName+":"+ ui->msgEdit->text();
    //将信息发送给服务器
    socket->write(msg.toLocal8Bit());

    //将msg的文本清空
    ui->msgEdit->clear();

}

void Second::on_disBtn_clicked()//离线按钮对应的槽函数
{
    QString msg = userName+":"+ "离开了聊天室,尔等也退下吧";
    socket->write(msg.toLocal8Bit());

    socket->disconnectFromHost();
}

 widget.cpp

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

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

    //窗口图标设计
    this->setWindowTitle("腾讯QQ");
    this->setWindowIcon(QIcon(":/pictrue/20573cf63610bed.jpg"));

    //连接登录Btn信号与槽
    connect(ui->pushButton_2,&QPushButton::clicked,this,&Widget::my_slot);

    ui->zhuceBtn->setStyleSheet("border:1px solid transparent;");
    ui->mimaBtn->setStyleSheet("border:1px solid transparent;");//取消边框

/**********************标签设置****************************/
    //设置标签背景(动态图)
//    QMovie *mv = new QMovie("/*************路径*************/");
//    ui->beijinglabel->setMovie(mv);
//    mv->start();
    //让标签自动使用标签
    ui->beijinglabel->setPixmap(QPixmap(":/pictrue/wKjg2lvGWoCAJlJxAADOBePmF24715.jpg"));
    ui->beijinglabel->setScaledContents(true);

    //设置左上角的标签
//    ui->qqlable->setPixmap(QPixmap(":/pictrue/20573cf63610bed.jpg"));
//    ui->qqlable->setScaledContents(true);
//    ui->qqlable->resize(30,30);//重新设置大小

/**********************登录设置*******************************/






}

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


void Widget::my_slot()//登录按钮对应的槽函数
{
    QString userName =  ui->zhanghaoEdit->text();//获取账号
    QString passWord =  ui->mimaEdit->text();//获取密码


    //判断登录条件是否满足
    if(userName=="admin"&&passWord=="123456")
    {
        //满足登录条件跳转到聊天室页面
//        qDebug() << "deng";
//        this->close();
         emit jump();

        this->hide();//将自己的页面隐藏


    }else
    {
       // qDebug() << "";
        QMessageBox::information(this,"提示:","账号或密码错误请重新输入");
        //ui->zhanghaoEdit->clear();

    }

}

second的ui界面 

widget的ui界面 

 

实现效果: 

运行出的窗口

 

 密码输入错误弹出的消息对话框和启动服务器成功界面

输入信息上线成功显示界面 

 消息发送成功界面

离线显示下线信息

 

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

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

相关文章

2023-10-21 LeetCode每日一题(统计无向图中无法互相到达点对数)

2023-10-21每日一题 一、题目编号 2316. 统计无向图中无法互相到达点对数二、题目链接 点击跳转到题目位置 三、题目描述 给你一个整数 n &#xff0c;表示一张 无向图 中有 n 个节点&#xff0c;编号为 0 到 n - 1 。同时给你一个二维整数数组 edges &#xff0c;其中 ed…

Python Pandas数据处理作图——波尔共振实验

import matplotlib.pyplot as plt import pandas as pd from pylab import mplmpl.rcParams["font.sans-serif"] ["SimHei"]data {频率比例w/wr: [1.036, 1.030, 1.025, 1.020, 1.012, 1.007, 1.002,0.997,0.993,0.990,0.986,0.977,0.969],振幅测量值θ&…

每日一练Day11

一、单选 1. 下面哪个标识符是合法的&#xff1f; A 9HelloWorld B _Hello World C Hello*World D Hello$World 答案 D 解析&#xff1a; Java标识符由字母、数字、_&#xff08;下划线&#xff09;、美元符号或人民币符号组成。不能由数字开头。关键字不能作为标识符…

#1024 程序员节 大图像中的小目标检测——基于YOLOV8+OnnxRuntime部署+滑动窗口+Zbar的条码检测研究

文章目录 前言1 训练一个YOLOV8的一维码检测模型2 创建滑动窗口2.1 模块导入与测试图片展示2.2 创建滑动窗口检测&#xff0c;窗口大小为&#xff08;640,640&#xff09;&#xff0c;滑动距离为640。对不足&#xff08;640&#xff0c;640&#xff09;的窗口进行填充 3 创建on…

并发编程-并发三大特性

并发三大特性 并发编程Bug源头&#xff1a;原子性、可见性和有序性问题。 原子性 一个或多个操作&#xff0c;要么全部执行且在执行过程中不被任何因素打断&#xff0c;要么全部不执行。 注意&#xff1a;不采取任何的原子性保障措施的自增操作并不是原子性的&#xff0c;比…

【题解 树形dp 拆位】 树上异或

「KDOI-06-S」树上异或 题目描述 给定一棵包含 n n n 个节点的树&#xff0c;第 i i i 个点有一个点权 x i x_i xi​。 对于树上的 n − 1 n-1 n−1 条边&#xff0c;每条边选择删除或不删除&#xff0c;有 2 n − 1 2^{n-1} 2n−1 种选择是否删除每条边的方案。 对于…

Vue中的响应式原理是如何实现的?

Vue中的响应式原理是通过使用Vue的响应式系统来实现的。这个系统依赖于JavaScript的Object.defineProperty方法&#xff0c;以及ES6的Proxy对象&#xff08;在Vue 3中&#xff09;。 下面是Vue中响应式原理的概述&#xff1a; 1&#xff1a;数据初始化&#xff1a; 在Vue组件…

【面试HOT100】链表树

系列综述&#xff1a; &#x1f49e;目的&#xff1a;本系列是个人整理为了秋招面试的&#xff0c;整理期间苛求每个知识点&#xff0c;平衡理解简易度与深入程度。 &#x1f970;来源&#xff1a;材料主要源于LeetCodeHot100进行的&#xff0c;每个知识点的修正和深入主要参考…

Java面向对象(基础)--方法应用

文章目录 一、方法的重载介绍案例&#xff08;1&#xff09;案例1 练习&#xff08;1&#xff09;练习1&#xff08;2&#xff09;练习2&#xff08;3&#xff09;练习3&#xff08;4&#xff09;练习4 二、可变个数形参的方法介绍举例&#xff08;1&#xff09;举例1&#xff…

计算机组成原理 new07 真值和机器数 无符号整数 定点整数 定点小数 $\color{red}{Δ}$

文章目录 真值和机器数 无符号整数无符号整数的定义无符号整数的特征无符号整数的表示范围无符号整数的加法无符号数的减法 有符号整数(定点整数)有符号整数的定义原码原码的特点反码反码的特点补码补码的特点快速求解n位负数补码的方法为什么补码能够多表示一个范围(重点)变形…

java1.8新特性流

案例描述 今天跟着黑马程序员的视频&#xff0c;完成“瑞吉外卖”项目的菜品信息管理模块的时候&#xff0c;遇到了一个比较陌生的写法 用到了Java8的新特性 stream().map((item) -> {}).collect() List<DishDto> collect records.stream().map((item) -> {DishDt…

人工智能(5):深度学习简介

1 深度学习 —— 神经网络简介 深度学习&#xff08;Deep Learning&#xff09;&#xff08;也称为深度结构学习【Deep Structured Learning】、层次学习【Hierarchical Learning】或者是深度机器学习【Deep Machine Learning】&#xff09;是一类算法集合&#xff0c;是机器学…

MySQL表操作—存储

建表&#xff1a; mysql> create table sch( -> id int primary key, -> name varchar(50) not null, -> glass varchar(50) not null -> ); Query OK, 0 rows affected (0.01 sec) 插入数据&#xff1a; mysql> insert into sch (id,name,…

【微信小程序】6天精准入门(第5天:利用案例与后台的数据交互)附源码

一、什么是后台交互&#xff1f; 在小程序中&#xff0c;与后台交互指的是小程序前端与后台服务器之间的数据通信和请求处理过程。通过与后台交互&#xff0c;小程序能够获取服务器端的数据、上传用户数据、发送请求等。 小程序与后台交互可以实现数据的传输、用户认证、实时消…

Babylonjs学习笔记(一)——搭建基础场景

React typescript umi Babylonjs 搭建基础场景 yarn add --save babylonjs babylonjs-loaders 1、封装基础场景 import { Engine, Scene } from "babylonjs"; import { useEffect,useRef,FC } from "react"; import "./index.less"type Prop…

自用bat脚本,命令

redis配置环境变量后 关机脚本 redis-server --service-stop启动脚本 :: 注释 rem echo off cd /d d:\\Redis :: redis-cli :: shutdown :: exit :: netstat -ano |findstr "6639" :: taskkill /pid {pid} /F redis-server redis.windows.conf pausecmd中替代gr…

BFS专题8 中国象棋-马-无障碍

题目&#xff1a; 样例&#xff1a; 输入 3 3 2 1 输出 3 2 1 0 -1 4 3 2 1 思路&#xff1a; 单纯的BFS走一遍即可&#xff0c;只是方向坐标的移动变化&#xff0c;需要变化一下。 代码详解如下&#xff1a; #include <iostream> #include <vector> #include…

上次的那段代码后续

之前写了一篇文章&#xff0c;说是一个要修改一个代码&#xff0c;很多人评论说代码说得不清不楚&#xff0c;不过在评论说又解释了一波之后&#xff0c;大家至少对这个代码有理解了&#xff0c;至少知道这个代码是做什么事情了。 如果是你&#xff0c;会不会修改这段代码&…

数据结构初阶——时间复杂度

朋友们我们又见面了&#xff0c;今天我们来学习数据结构的时间复杂度&#xff0c;在讲数据结构之前&#xff0c;大家可能只知道我们学习的是数据结构&#xff0c;但是还是不知道数据结构的具体定义&#xff0c;其实就是在内存上的数据。然后我们就像通讯录一样对它进行增删查改…

Qt 目录操作(QDir 类)及展示系统文件实战 QFilelnfo 类介绍和获取文件属性项目实战

一、目录操作(QDir 类) QDir 类提供访问系统目录结构 QDir 类提供对目录结构及其内容的访问。QDir 用于操作路径名、访问有关路径和文件的信息以及操作底层文件系统。它还可以用于访问 Qt 的资源系统 Qt 使用“/”作为通用目录分隔符&#xff0c;与“/”在 URL 中用作路径分…