<3>[QTCN]图片网络传输工具(客户端)

目录

  • 参考
  • 实现
    • PictureTcpClient.pro
    • main.cpp
    • picturetcpclient.h
    • picturetcpclient.cpp
    • picturetcpclient.ui
  • 效果
  • 源码
  • 模糊知识点

参考

<6>[QTCN]图片网络传输工具(客户端)

说明:图片网络传输工具(客户端)

亮点:图片网络传输

实现

PictureTcpClient.pro

QT       += network

main.cpp

#include "picturetcpclient.h"
#include 
#include
int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
    PictureTcpClient w;
    QFont font;
    font.setPixelSize(25);
    w.setFont(font);
    w.show();
    return a.exec();
}

picturetcpclient.h


#ifndef PICTURETCPCLIENT_H
#define PICTURETCPCLIENT_H

#include 
#include
#include
#include
#include
#pragma execution_character_set("utf-8")

QT_BEGIN_NAMESPACE
namespace Ui { class PictureTcpClient; }
QT_END_NAMESPACE

class PictureTcpClient : public QWidget
{
    Q_OBJECT

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

    void InitTcp();
    void ChangeEnable(bool isEnable);
    void ConnectToServer();     //连接服务器
    void SendData();            //发送数据
    QStringList GetFileNames(QString filter);   //获取打开对话框中指定格式的文件列表
    void DelayTime(int ms);                     //延时等待功能
    QByteArray GetPicData(QString fromPic);

private slots:
    void on_btnConnect_clicked();

    void on_btnDisConnect_clicked();

    void on_btnSend_clicked();

    void on_btnSelectImg_clicked();

    void on_btnClear_clicked();

    void on_btnSendImg_clicked();

    void conSuc();              //连接成功
    void ReadData();            //读取数据
    void DisplayError(QAbstractSocket::SocketError);

private:
    Ui::PictureTcpClient *ui;

    QTcpSocket *m_tcpClient;
};

#endif // PICTURETCPCLIENT_H

picturetcpclient.cpp


#include "picturetcpclient.h"
#include "ui_picturetcpclient.h"
#pragma execution_character_set("utf-8")

PictureTcpClient::PictureTcpClient(QWidget *parent)
    : QWidget(parent)
    , ui(new Ui::PictureTcpClient)
{
    ui->setupUi(this);
    this->setWindowIcon(QIcon(":/1.ico"));
    this->setWindowTitle("图片网络传输工具(客户端)");
    this->ChangeEnable(false);
    this->InitTcp();
}

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

void PictureTcpClient::InitTcp()
{
    m_tcpClient = new QTcpSocket(this);
    m_tcpClient->abort();               //中断已有的链接
    connect(m_tcpClient,SIGNAL(readyRead()),this,SLOT(ReadData()));
    connect(m_tcpClient,SIGNAL(error(QAbstractSocket::SocketError)),\
            this,SLOT(DisplayError(QAbstractSocket::SocketError)));

    //该信号在调用connectToHost()并成功建立连接之后发出。
    connect(m_tcpClient, SIGNAL(connected()),this, SLOT(conSuc()));
}

void PictureTcpClient::ChangeEnable(bool isEnable)
{
    ui->btnConnect->setEnabled(!isEnable);
    ui->btnDisConnect->setEnabled(isEnable);
    ui->btnSend->setEnabled(isEnable);
    ui->btnSendImg->setEnabled(isEnable);
}

//连接服务器
void PictureTcpClient::ConnectToServer()
{
    m_tcpClient->abort();
    m_tcpClient->connectToHost(ui->txtIP->text(),ui->txtPort->text().toInt());
}

//连接成功
void PictureTcpClient::conSuc()
{
    ui->labInfo->setText("提示:连接成功");
    this->ChangeEnable(true);
}

//发送数据
void PictureTcpClient::SendData()
{
    // 获取 QTextEdit 中的纯文本内容,转换为Latin-1单字节编码的字节数组
    m_tcpClient->write(ui->txtSendData->toPlainText().toUtf8());
}

//读取数据
void PictureTcpClient::ReadData()
{
    QByteArray read=m_tcpClient->readAll();
    if (!read.isEmpty())
    {
        ui->txtGetData->append(QString::fromUtf8(read));
    }
}

void PictureTcpClient::DisplayError(QAbstractSocket::SocketError)
{
    ui->labInfo->setText(QString("提示:连接失败,原因(%1)").arg(m_tcpClient->errorString()));
    this->ChangeEnable(false);
}

//获取打开对话框中指定格式的文件列表
QStringList PictureTcpClient::GetFileNames(QString filter)
{
    QStringList fileNames;
    fileNames=QFileDialog::getOpenFileNames(this,"选择文件",QCoreApplication::applicationDirPath(),filter);
    if (fileNames.isEmpty())
    {
        return QStringList();
    }
    else
    {
        return fileNames;
    }
}

//延时等待功能
void PictureTcpClient::DelayTime(int ms)
{
    QTime t=QTime::currentTime().addMSecs(ms);//当前时间的基础上增加ms毫秒,得到一个目标时间点t
    while(QTime::currentTime()<t)
    {/*处理当前线程的事件队列,并等待最多100毫秒来接收新的事件。
      *处理所有类型的事件,包括定时器事件、绘图事件等
      *通过不断处理事件,可以确保程序在等待期间仍然能够响应其他事件,以避免程序无响应或阻塞*/
        QCoreApplication::processEvents(QEventLoop::AllEvents,100);
    }
}

QByteArray PictureTcpClient::GetPicData(QString fromPic)
{
    QImage img(fromPic);
    // 保存图像数据到 QByteArray
    QByteArray ba;
    QBuffer buf(&ba);
    buf.open(QIODevice::WriteOnly);
    img.save(&buf,"JPG");               //按照JPG解码保存数据
    buf.close();

    QByteArray cc=qCompress(ba,1);      // 对图像数据进行压缩

    QByteArray hh;
    hh=cc.toBase64();                   //获取Base64数据
    return hh;
}


void PictureTcpClient::on_btnConnect_clicked()
{
    this->ConnectToServer();
}


void PictureTcpClient::on_btnDisConnect_clicked()
{
    m_tcpClient->disconnectFromHost();      //断开QTcpSocket对象与远程主机的连接的函数
    ui->labInfo->setText(tr("提示:断开连接"));
    this->ChangeEnable(false);
}


void PictureTcpClient::on_btnSend_clicked()
{
    this->SendData();
}


void PictureTcpClient::on_btnSelectImg_clicked()
{
   ui->listWidget->addItems(this->GetFileNames("图片文件(*.jpg)"));
}


void PictureTcpClient::on_btnClear_clicked()
{
   if (ui->listWidget->count()>0)
        ui->listWidget->clear();
}


void PictureTcpClient::on_btnSendImg_clicked()
{
   if (ui->listWidget->count()<=0)                      //没有图片发送则返回
        return;
   QListWidgetItem *myitem;
   int intervalTime=ui->txtTime->text().toInt();
   qDebug()<<"图片 ="<<ui->listWidget->count();
   for (int i=0;i<ui->listWidget->count();i++)
   {
        qDebug()<<"i="<<i;
        myitem=ui->listWidget->item(i);
        QByteArray myPicData=this->GetPicData(myitem->text());
        if (ui->rbtnJY->isChecked())                    //数据校验
        {
            QByteArray ba;
            QDataStream out(&ba,QIODevice::WriteOnly);  //使用数据流写入数据
            out.setVersion(QDataStream::Qt_4_7);        //设置数据流版本,客户端和服务器端使用版本要相同
            /*预留两个字节的空间来存放文件大小信息
             * 将0的quint16类型的数据写入到数据流中*/
            out<<(quint16)0;                            //放置文件大小信息
            out<<myPicData;                             //将实际的文件数据写入到数据流中
            out.device()->seek(0);                      //将数据流的位置指针移动到起始位置。可以在起始位置再次写入文件大小信息
            /*文件数据的大小减去预留的两个字节后的值*/
            out<<(quint16)(ba.size()-sizeof(quint16));  //将实际的文件大小信息写入到数据流中
            myPicData.clear();
            myPicData=ba;
        }
        m_tcpClient->write(myPicData);
        this->DelayTime(intervalTime);
   }
    QMessageBox::information(this,"提示","恭喜你!发送图片完成!");
}


picturetcpclient.ui

<3>[QTCN]图片网络传输工具(客户端)_第1张图片

效果

源码

Gitee:03PictureTcpClient[QTCN]图片网络传输工具(客户端)

模糊知识点

  1. 设置数据流版本,放置文件大小信息
QByteArray ba;
QDataStream out(&ba,QIODevice::WriteOnly);  //使用数据流写入数据
out.setVersion(QDataStream::Qt_4_7);        //设置数据流版本,客户端和服务器端使用版本要相同
/*预留两个字节的空间来存放文件大小信息
 * 将0的quint16类型的数据写入到数据流中*/
out<<(quint16)0;                            //放置文件大小信息
out<<myPicData;                             //将实际的文件数据写入到数据流中
out.device()->seek(0);                      //将数据流的位置指针移动到起始位置。可以在起始位置再次写入文件大小信息
/*文件数据的大小减去预留的两个字节后的值*/
out<<(quint16)(ba.size()-sizeof(quint16));  //将实际的文件大小信息写入到数据流中
  1. 返回值QByteArray,在#pragma execution_character_set("utf-8")编程环境下,使用QString::toUtf8()

toUtf8()函数将字符串转换为UTF-8编码格式。UTF-8是一种可变长度的Unicode编码,它可以表示世界上几乎所有的字符,并且与ASCII兼容。UTF-8编码在国际化和多语言支持方面非常常用,因为它可以表示各种语言的字符。

toLatin1()函数将字符串转换为Latin1编码格式。Latin1,也称为ISO-8859-1,是一个简单的单字节编码,它可以表示西欧语言中的字符。使用Latin1编码时,每个字符占用一个字节。

区别:

编码范围:toUtf8()函数能够表示更广泛的字符范围,包括Unicode字符集中的所有字符,而toLatin1()函数只能表示Latin1字符集中的字符。

字节长度:UTF-8编码是一种可变长度的编码方案,一个字符可能由1到4个字节组成,而Latin1编码是一种固定长度的编码方案,每个字符只占用一个字节。

如果你的应用程序需要处理多语言、国际化或Unicode字符集中的字符,那么通常建议使用toUtf8()函数。
如果你只需要处理简单的单字节字符,比如英文字符或西欧语言字符,那么使用toLatin1()函数可能更为合适。

需要注意的是,在进行编码转换时,要确保目标编码能够正确表示源字符串中的所有字符。
如果源字符串包含了目标编码中不支持的字符,转换结果可能会出现乱码或数据丢失的情况。

你可能感兴趣的:(QTCN,qt)