<6>[QTCN]图片网络传输工具(客户端)
说明:图片网络传输工具(客户端)
亮点:图片网络传输
QT += network
#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();
}
#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
#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,"提示","恭喜你!发送图片完成!");
}
Gitee:03PictureTcpClient[QTCN]图片网络传输工具(客户端)
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)); //将实际的文件大小信息写入到数据流中
#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()函数可能更为合适。需要注意的是,在进行编码转换时,要确保目标编码能够正确表示源字符串中的所有字符。
如果源字符串包含了目标编码中不支持的字符,转换结果可能会出现乱码或数据丢失的情况。