QT 仿QQ 聊天软件
前言
用QT 写了一个QQ 写了添加好友 发送文件 发送信息 登录 等功能
不讲完整代码 太多了 写的间隔周期也比较久 所以抓一些我觉得比较难的讲。








一、UI
1.登录界面

UI没什么好说的 我是纯代码写的界面 喜欢用UI拖的就直接拖就可以了。
简单说一下
首先是这个界面
几乎是一个裸界面 除了登录跟找回密码跟那个动图 其他都没写
登录的时候用QStackedWidget 切换成登录的界面 然后发信息给服务器校验一下就好了是否登录成功 成功的话就把这个界面隐藏换成主界面就好了。
动图的话采用
QMovie *movie = new QMovie("F:/QTpro/Work/FunTest/TcpCommSocket/Paint/LoginTop.gif");QWidget* mWidget = new QWidget();mWidget->setFixedSize(430,350);
但是我这里我写的是比较难受的 因为用代码写更偏向于用QBoxLayout去布局 但是用了这个上面的3个按钮就没办法布局上去 我就直接利用move的方式移动到动图上面去的 如果有的可以教一下
2.主界面
1.名字以及个性签名

主界面要讲的应该不多 都是常规控件的使用方式
首先是这个名字跟他的那个个性签名
我这边的解决方式是 重写一个QWidget
然后用QStackedWidget 生成2个界面 一个是 QPushButton 跟 一个 QLineEdit
然后重载eventFilter 在点击的时候切换 就可以做到。
然后名字跟个性签名更改的时候发信息给服务器让服务器保存个性签名跟名字 下次进来的时候就会沿用你现在的网名跟个性签名
bool LineEditWidget::eventFilter(QObject *watched, QEvent *event)
{QStackedWidget* mSWidget = this->findChild<QStackedWidget*>("titleSWidget");QPushButton* btn = this->findChild<QPushButton*>("btn");QLineEdit* edit = this->findChild<QLineEdit*>("edit");if(watched == edit){if(event->type() == QEvent::FocusOut){_str = edit->text();QString str1 = PubFunction::getElidedText(btn->font(),_str,btn->width(),2);btn->setText(str1);mSWidget->setCurrentIndex(0);emit editChange(edit->text());}else if(event->type() == QEvent::KeyPress){QKeyEvent* keyEvent = static_cast<QKeyEvent*>(event);if(keyEvent->key() == 16777220){
// _str = edit->text();
// QString str1 = PubFunction::getElidedText(btn->font(),_str,btn->width());
// btn->setText(str1);mSWidget->setCurrentIndex(0);// emit editChange(edit->text());}}}return QWidget::eventFilter(watched,event);
}
2.好友列表

好友列表其实是用了一个自动滚动去 QScrollArea
然后画了红色线的就是一个就是一个QTableView 好友列表那块是一个表头 然后当中的好友就是一个项 好友项是画出来的 详细看等会看下面代码 然后点击表头的时候是需要重写鼠标事件 鼠标点击表头的时候要直接控制View的高度 我尝试过用QBoxLayout 去强制卡布局 但是效果不好 因为表头的高度是固定的 项也是固定的 所以在点击事件直接控制表头是我的解决方式 具体看下面代码
//----------------View 好友项的绘画if(index.column() == 0){const int spacing = 10;const int buttonWidth = 40;const int buttonHeight = 40;const QVariantList list = index.model()->index(index.row(),0).data().toList();const QString name = list.at(1).toString();const QString remark = list.at(2).toString();const QString signature = list.at(3).toString();const QString paint = list.at(4).toString();QStyleOptionButton button;button.rect = QRect(option.rect.x() + spacing,option.rect.y() + spacing,buttonWidth,buttonHeight);QWidget* pWidget = _btnPaint;pWidget->style()->drawControl(QStyle::CE_PushButton,&button,painter,pWidget);QFont font;font.setPixelSize(13);painter->setFont(font);QRect nameRect = QRect(option.rect.x() + buttonWidth + spacing * 2,option.rect.y() + spacing,option.rect.width(),option.rect.height() / 2 - 10);QString mos = remark;if(!remark.isEmpty()){const QString addStr = "(" + name + ")";mos += addStr;}else{const QString addStr = name;mos += addStr;}QTextOption o;o.setAlignment(Qt::AlignVCenter);painter->drawText(nameRect,mos,o);font.setPixelSize(12);painter->setFont(font);QPen pen;pen.setColor(QColor(80,80,80));painter->setPen(pen);QRect signatureRect = QRect(option.rect.x() + buttonWidth + spacing * 2,option.rect.y() + option.rect.height() / 2 - spacing + spacing ,option.rect.width(),option.rect.height() / 2 - 10);painter->drawText(signatureRect,signature,o);}
//表头点击显示隐藏的方式
void ContactTableHeader::mousePressEvent(QMouseEvent *e)
{if (e->button() == Qt::LeftButton){int logicalIndex = logicalIndexAt(e->pos());if(logicalIndex == 0){_isHide = !_isHide;if(!_isHide){_pWidget->setStyleSheet("QPushButton{border-image:url(:/Main/Paint/arrow_d.png);}");}else{_pWidget->setStyleSheet("QPushButton{border-image:url(:/Main/Paint/arrow_r_g.png);}");}emit HideOrShow(_isHide);}}update();
}this->connect(header,&ContactTableHeader::HideOrShow,this,[=](bool isHide){if(isHide){_viewHeight = 35;}else{_viewHeight = 35 + tableModel->GetSize() * 60;}emit HeaderClicked(_viewHeight);this->setFixedHeight(_viewHeight);tableDelegate->SetHide(isHide);tableModel->RefrushModelData();});
3.聊天界面

我希望这些红色的可以帮助你理解我的想法 他就是依靠QBoxLayout布局去卡着这些界面的存在 所以才会有这些东西
首先严格来说这里麻烦的部分只有右边的文件框 也是用了TableView绘画的
然后聊天框也是使用QWidget 调用 paint绘画的(这部分不是我自己写的 借鉴?或者说抄一位前辈的 时间久远我也想起不来是哪位 估计抓点关键词搜索一下就好了。)代码看下面
文件列表的代码painter->setRenderHint(QPainter::Antialiasing,true);QFont font;font.setPixelSize(11);font.setFamily("微软雅黑");painter->setFont(font);if(index.column() == 0){int typeMapLeftSpaceing = option.rect.x() + 10;int typeMapTopSpaceing = option.rect.y() + 10;int typeMapWidth = 45;int typeMapHeight = 45;int mapLeftSpaceing = typeMapLeftSpaceing + typeMapWidth + 5;int mapTopSpaceing = typeMapTopSpaceing;int mapWidth = 15;int mapHeight = 15;int nameLeftSpaceing = mapLeftSpaceing + mapWidth + 5;int nameTopSpaceing = typeMapTopSpaceing;int nameWidth = 200;int nameHeight = 15;// int sizeLeftSpaceing = nameLeftSpaceing + nameWidth + 1;
// int sizeTopSpaceing = typeMapTopSpaceing;
// int sizeWidth = 100;
// int sizeHeight = 20;int sliderLeftSpaceing = mapLeftSpaceing;int sliderTopSpaceing = 5 + mapTopSpaceing + nameHeight;int sliderWidth = 220;int sliderHeight = 5;double sliderDrawWidth = 0;int textLeftSpaceing = mapLeftSpaceing;int textTopSpaceing = sliderTopSpaceing + sliderHeight + 5;int textWidth = 140;int textHeight = 15;int sureButtonLeftSpaceing = textLeftSpaceing + textWidth + 10;int sureButtonTopSpaceing = textTopSpaceing;int sureButtonWidth = 30;int sureButtonHeight = 15;int quitButtonLeftSpaceing = sureButtonLeftSpaceing + sureButtonWidth + 10;int quitButtonTopSpaceing = textTopSpaceing;int quitButtonWidth = 30;int quitButtonHeight = 15;const QVariantList list = index.model()->index(index.row(),0).data().toList();const QString name = list.at(0).toString();const bool isSent = list.at(1).toBool();const QString asSize = list.at(2).toString();const QString fileID = list.at(3).toString();const QString totalSize = list.at(4).toString();const QString text = list.at(5).toString();const bool isSuccess = list.at(6).toBool();//---------------mapQPixmap map;const QString suffix = name.split(".").last();if(suffix == "txt"){map.load(":/FilePro/Paint/txt.png");}else if(suffix == "exe"){map.load(":/FilePro/Paint/exe.png");}else{map.load(":/FilePro/Paint/unknown.png");}QRect typeMapRect = QRect(typeMapLeftSpaceing,typeMapTopSpaceing,typeMapWidth,typeMapHeight);painter->drawPixmap(typeMapRect,map);//----------------mapQPixmap map1;if(isSent){map1.load(":/FilePro/Paint/Send.png");}else{map1.load(":/FilePro/Paint/Accept.png");}QRect mapRect = QRect(mapLeftSpaceing,mapTopSpaceing,mapWidth,mapHeight);painter->drawPixmap(mapRect,map1);//------------name;QString strName = PubFunction::getElidedText(font,name,nameWidth,1);QString strSize = "(" + asSize + "/" + totalSize + ")";QRect nameRect = QRect(nameLeftSpaceing,nameTopSpaceing,nameWidth,nameHeight);QTextOption o;o.setAlignment(Qt::AlignLeft);painter->drawText(nameRect,strName,o);//------------size//-------------sliderpainter->fillRect(QRect(sliderLeftSpaceing,sliderTopSpaceing,sliderWidth,sliderHeight),QColor(180,180,180));double pro = 0.0;if(!asSize.isEmpty()){pro = asSize.toDouble() / totalSize.toDouble();}sliderDrawWidth = pro * (double)sliderWidth;painter->fillRect(QRect(sliderLeftSpaceing,sliderTopSpaceing,(int)sliderDrawWidth,sliderHeight),QColor(0,255,0));//-------------textQRect textRect = QRect(textLeftSpaceing,textTopSpaceing,textWidth,textHeight);painter->drawText(textRect,text,o);//--------------button//如果已经点击了同意就隐藏同意按钮if(!isSuccess){QRect sureRect = QRect(sureButtonLeftSpaceing,sureButtonTopSpaceing,sureButtonWidth,sureButtonHeight);QPen pen;pen.setColor(QColor(39,134,228));painter->setPen(pen);if(sureRect.contains(_mousePoint)){if(ButtonState == 1){pen.setColor(QColor(30,30,30));painter->setPen(pen);}}painter->drawText(sureRect,"接受",o);}QRect quitRect = QRect(quitButtonLeftSpaceing,quitButtonTopSpaceing,quitButtonWidth,quitButtonHeight);QPen pen;pen.setColor(QColor(39,134,228));painter->setPen(pen);if(quitRect.contains(_mousePoint)){if(ButtonState == 1){pen.setColor(QColor(30,30,30));painter->setPen(pen);}}painter->drawText(quitRect,"拒绝",o);}
聊天界面的代码QPainter painter(this);painter.setRenderHints(QPainter::Antialiasing | QPainter::SmoothPixmapTransform);//消锯齿int preAddLength = 0;for(int i = 0 ; i < _megList.size(); i++){painter.setPen(Qt::NoPen);painter.setBrush(QBrush(Qt::gray));MegInfo info = _megList.at(i);int heightSpaceing = 10;if(i != 0){heightSpaceing = preAddLength;}fontRect(info,heightSpaceing);preAddLength = info._kuangLeftRect.height() + info._kuangLeftRect.y();if(info._megSource == MegToFriend){//头像// painter.drawRoundedRect(m_iconLeftRect,m_iconLeftRect.width(),m_iconLeftRect.height());// painter.drawPixmap(info._iconLeftRect, info._leftPixmap);//框加边QColor col_KuangB(234, 234, 234);painter.setBrush(QBrush(col_KuangB));painter.drawRoundedRect(info._kuangLeftRect.x()-1,info._kuangLeftRect.y()-1,info._kuangLeftRect.width()+2,info._kuangLeftRect.height()+2,4,4);//框QColor col_Kuang(255,255,255);painter.setBrush(QBrush(col_Kuang));painter.drawRoundedRect(info._kuangLeftRect,4,4);//三角QPointF points[3] = {QPointF(info._sanjiaoLeftRect.x(),info._sanjiaoLeftRect.y() + 30),QPointF(info._sanjiaoLeftRect.x() + info._sanjiaoLeftRect.width(),info._sanjiaoLeftRect.y() + 25),QPointF(info._sanjiaoLeftRect.x() + info._sanjiaoLeftRect.width(),info._sanjiaoLeftRect.y() + 35),};QPen pen;pen.setColor(col_Kuang);painter.setPen(pen);painter.drawPolygon(points, 3);//三角加边QPen penSanJiaoBian;penSanJiaoBian.setColor(col_KuangB);painter.setPen(penSanJiaoBian);painter.drawLine(QPointF(info._sanjiaoLeftRect.x() - 1, info._sanjiaoLeftRect.y() + 30), QPointF(info._sanjiaoLeftRect.x() + info._sanjiaoLeftRect.width(),info._sanjiaoLeftRect.y() + 24));painter.drawLine(QPointF(info._sanjiaoLeftRect.x() - 1, info._sanjiaoLeftRect.y() + 30), QPointF(info._sanjiaoLeftRect.x() + info._sanjiaoLeftRect.width(),info._sanjiaoLeftRect.y() + 36));//内容QPen penText;penText.setColor(QColor(51,51,51));painter.setPen(penText);QTextOption option(Qt::AlignLeft | Qt::AlignVCenter);option.setWrapMode(QTextOption::WrapAtWordBoundaryOrAnywhere);painter.setFont(this->font());painter.drawText(info._textLeftRect, info._megString,option);}else if(info._megSource == MegToMySelf){// 自己//头像// painter.drawRoundedRect(m_iconRightRect,m_iconRightRect.width(),m_iconRightRect.height());// painter.drawPixmap(info._iconRightRect, info._rightPixmap);//框QColor col_Kuang(75,164,242);painter.setBrush(QBrush(col_Kuang));painter.drawRoundedRect(info._kuangRightRect,4,4);//三角QPointF points[3] = {QPointF(info._sanjiaoRightRect.x() + info._sanjiaoRightRect.width(),info._sanjiaoLeftRect.y() + 30),QPointF(info._sanjiaoRightRect.x(),info._sanjiaoLeftRect.y() + 25),QPointF(info._sanjiaoRightRect.x(),info._sanjiaoLeftRect.y() + 35),};QPen pen;pen.setColor(col_Kuang);painter.setPen(pen);painter.drawPolygon(points, 3);//内容QPen penText;penText.setColor(Qt::white);painter.setPen(penText);QTextOption option(Qt::AlignLeft | Qt::AlignVCenter);option.setWrapMode(QTextOption::WrapAtWordBoundaryOrAnywhere);painter.setFont(this->font());painter.drawText(info._textRightRect,info._megString,option);}else if(info._megSource == MegToTime){// 时间QPen penText;penText.setColor(QColor(153,153,153));painter.setPen(penText);QTextOption option(Qt::AlignCenter);option.setWrapMode(QTextOption::WrapAtWordBoundaryOrAnywhere);QFont te_font = this->font();te_font.setFamily("MicrosoftYaHei");te_font.setPointSize(10);painter.setFont(te_font);painter.drawText(info._timeRect,info._megString,option);}}emit UpdateHeight(preAddLength + 15);
4.好友添加界面
没啥难点 拖就完事了嗷
二、NetWork
1.注册Socket
最重要的就是注册吧 因为服务器分不清你的账号到底是那个 比如 我现在的账号是1 我连接上了服务器 服务器此刻是不知道我的账号是几 只知道一个Socket连接上了 所以我们就需要发送一个信息告诉服务器 这个连接上的Socket的服务器是1 所以只需要发送一个让服务器接受后续的聊天跟发文件的时候服务器就可以根据你的账号进行一个转发
typedef struct _TCP_ENROLL
{unsigned int _pktHead;long long _pktLoginAccount; //账号char _pktOther[2016]; //long long _pktCrc; //CRCunsigned int _pktFoot;
}TCP_ENROLL;
2.登录
在登录界面点击登录的时候需要 向服务器发送信息 然后由服务器判断账号密码是否正确来判断是不是没问题 所以我们只需要声明一个结构体 然后发送 接受就可以了。这里好像没什么麻烦的
typedef struct _TCP_LOGIN_PKT
{unsigned int _pktHead;unsigned short _pktType; //long long _pktLoginAccount; //账号char _pktPasswd[32]; //密码char _pktName[64]; //名称char _pktSignature[64]; //签名char _pktOther[1856]; //long long _pktCrc; //CRCunsigned int _pktFoot;
}TCP_LOGIN_PKT;//发送
void TcpSocketLogin::WriteLogin(long long account, QString passwd)
{_loginState = -1;TCP_LOGIN_PKT pkt;pkt._pktHead = LOGIN_HEAD;pkt._pktLoginAccount = account;QString msg = PubFunction::EncryptPasswd(passwd);QByteArray passwdAry = msg.toLatin1();qDebug() << passwdAry;memcpy(&pkt._pktPasswd,passwdAry,sizeof(char) * 32);pkt._pktType = LOGIN_REQUEST;qint64 crc = PubFunction::Check_CRC16(&passwdAry);pkt._pktCrc = crc;memcpy(&pkt._pktName,"0",sizeof(char) * 64);memcpy(&pkt._pktSignature,"0",sizeof(char) * 64);memcpy(&pkt._pktOther,"0",sizeof(char) * 1856);pkt._pktFoot = LOGIN_FOOT;this->Write((char*)&pkt,sizeof(TCP_LOGIN_PKT));
}//接受
if(LOGIN_HEAD == head)
{TCP_LOGIN_PKT pkt;memcpy(&pkt,data+start,MAX_PKT_SIZE);start += MAX_PKT_SIZE;if(pkt._pktHead == LOGIN_HEAD || pkt._pktFoot == LOGIN_FOOT){if(pkt._pktType == LOGIN_SUCCESS){QByteArray nameAry(pkt._pktName);_loginName = QString::fromUtf8(nameAry);QByteArray signatureAry(pkt._pktSignature);_loginSignature = QString::fromUtf8(signatureAry);_loginState = 1;}else if(pkt._pktType == LOGIN_ERROR){_loginState = 0;}else if(pkt._pktType == LOGIN_ADD_SUCCESS){_addState = 1;}else if(pkt._pktType == LOGIN_ADD_ERROR){_addState = 0;}}
}
3.好友
首先每次注册一个账号的时候我们需要创建一个数据库 数据库里面存储的就是好友的信息 在登录的时候直接把好友返回回去就可以了 然后客户端这边接受然后给TableView 添加一个项就可以。
//数据库的创建if(!_db.isOpen()){return false;}QSqlQuery query(_db);const QString cFaceClock = QString("create table table%1(account varchar primary key,remake varchar,type int)").arg(dbName);bool isExec = query.exec(cFaceClock);if(!isExec){qDebug() <<query.lastError().text() << query.lastQuery();}return true;
//数据库的查询
bool AccountDB::ReadValue(QString str, QVariantList& valueList,int size)
{if(str.isEmpty())return false;if(size < 1)return false;QSqlQuery sql(_db);sql.exec(str);while(sql.next()){QStringList list;for(int i = 0; i < size; i++){QVariant data = sql.value(i);list.push_back(data.toString());}valueList.push_back(list);}if(valueList.size() == 0)return false;return true;
}const QString selectStr = QString("select account,remake from table%1").arg(dbName);const bool isRead = ReadValue(selectStr,list,2);return isRead;
客户端的读取 然后发送信号出去就好了。
else if(pkt._pktType == SELECT_BACK_FRIEND)
{QString account = QString::number(pkt._pktAccount);QByteArray pktName(pkt._pktName);QString name = QString::fromUtf8(pktName);QByteArray pktSign(pkt._pktSign);QString sign = QString::fromUtf8(pktSign);QByteArray pktRemark(pkt._pktRemark);QString remark = QString::fromUtf8(pktRemark);QStringList msg;msg.push_back(account);msg.push_back(name);msg.push_back(sign);msg.push_back(remark);_contactList.push_back(msg);
}
4.聊天
聊天唯一麻烦的点就是需要发送账号 所以需要在结构体定义个发送的账号 跟接受的账号 然后信息定义在2048之内 我看好像微信跟QQ一次性最大发送的信息也在2048左右 然后又服务器根据账号分发给对应的QTcpSocket
typedef struct _MSG_DATA_PKT
{unsigned short _pktHead; //协议头unsigned long long _pktFileId; //文件IDlong long _pktSendId; //发送的IDlong long _pktAcceptId; //接受的IDunsigned int _pktLength; //数据长度char _pktOther[4]; //保留char _pktData[1988]; //数据long long _pktCrc; //CRCunsigned short _pktFoot; //保留位
}MSG_DATA_PKT;void TcpSocketMsgObj::WriteMeg(QString data,QString account)
{MSG_DATA_PKT pkt;pkt._pktHead = DATA_MSG_HEAD;pkt._pktFileId = QDateTime::currentDateTime().toMSecsSinceEpoch();pkt._pktSendId = PubFunction::GetAccount().toLongLong();pkt._pktAcceptId = account.toLongLong();pkt._pktLength = data.size();memcpy(&pkt._pktData,data.toUtf8().data(),sizeof(char) * 1844);memcpy(&pkt._pktOther,"0",sizeof(char) * 4);pkt._pktCrc = 0;pkt._pktFoot = DATA_MSG_FOOT;char* charPkt = (char*)&pkt;QByteArray aryPkt(charPkt);qint64 crc = PubFunction::Check_CRC16(&aryPkt);pkt._pktCrc = crc;_msgPktMap[pkt._pktFileId] = pkt;bool isWrite = this->Write((char*)&pkt,sizeof(MSG_DATA_PKT));
}
5.文件
文件太多了 就挑一些比较重要的讲 就发送文件信息 跟 接受这2部分比较重要 其他的也差不多
const unsigned long long fileId = var._varFileId;const QString filePath = _fileNameMap.value(fileId);if(filePath.isEmpty()){return;}QFile file(filePath);const qint64 fileSize = file.size();const bool isOpen = file.open(QFile::ReadOnly);if(!isOpen){return;}unsigned int packNo = 0;qint64 offest = 0;_fileDataPktMap[fileId] = QList<FILE_DATA_PKT>();while(offest < fileSize){FILE_DATA_PKT pkt;pkt._pktHead = DATA_FILE_HEAD;pkt._pktPackNo = packNo;if(offest + DATA_MAX_SIZE >= fileSize){pkt._pktDataLength = fileSize - offest;}else{pkt._pktDataLength = DATA_MAX_SIZE;}const bool isSeek = file.seek(offest);if(!isSeek){qDebug() << "DataPkt PushBack Error";}QByteArray ary = file.read(pkt._pktDataLength);memcpy(&pkt._pktData,ary.data(),pkt._pktDataLength);pkt._pktDataOffset = offest;pkt._pktCrc = 0;pkt._pktFileId = fileId;pkt._pktAcceptId = var._varAcceptAccount.toLongLong();pkt._pktSendId = var._varSendAccount.toLongLong();packNo += 1;offest += pkt._pktDataLength;memcpy(&pkt._pktOther,"0",sizeof(char) * 4);pkt._pktFoot = DATA_FILE_FOOT;char* charPkt = (char*)&pkt;QByteArray crcAry(charPkt);qint64 crc = PubFunction::Check_CRC16(&crcAry);pkt._pktCrc = crc;QList<FILE_DATA_PKT>& mapList = _fileDataPktMap[fileId];mapList.append(pkt);file.close();
这部分是接受 const unsigned long long fileID = pkt._pktFileId;QString fileName = "";unsigned long long fileMaxSize = 0;if(_fileAcceptInfoMap.contains(fileID)){FILE_INFO_PKT pkt = _fileAcceptInfoMap[fileID];QByteArray bName(pkt._pktFileName);fileName = QString::fromUtf8(bName);fileMaxSize = pkt._pktFileSize;QByteArray md5Bytes(pkt._pktFileMD5);_fileMD5Map[fileID] = md5Bytes;}QFile file(PubFunction::fileDownPath() + fileName);if(!file.open(QFile::ReadWrite)){return;}const long long offest = pkt._pktDataOffset;QDataStream out(&file);file.seek(0);bool isSeek = file.seek(offest);if(!isSeek){return;}out.writeRawData(pkt._pktData,pkt._pktDataLength);unsigned long long& nowSize = _nFileSizeMap[pkt._pktFileId];nowSize += pkt._pktDataLength;QString sendAccount = QString::number(pkt._pktSendId);SignalVar var;var._varFileId = fileID;var._varPackNo = pkt._pktPackNo;var._varSendAccount = QString::number(pkt._pktAcceptId);var._varAcceptAccount = QString::number(pkt._pktSendId);if(nowSize >= fileMaxSize){file.close();//检验文件的MD5const QString fileName = file.fileName();QByteArray nowMD5 = PubFunction::MakeMd5(fileName).toLatin1();QByteArray readMD5 = _fileMD5Map[fileID];qDebug() <<fileName << nowMD5 << readMD5;if(nowMD5 == readMD5){//删除文件。_fileMD5Map.remove(fileID);_fileAcceptInfoMap.remove(fileID);_nFileSizeMap.remove(fileID);//发送FINISH 包//刷新UI百分比PushBackFinishPkt(var);QStringList list = QStringList() << QString::number(pkt._pktSendId) << QString::number(pkt._pktFileId) << QString::number(fileMaxSize);emit UpdateAcceptUIProgress(list);}}else{PushBackDataOk(var);QStringList list = QStringList() << QString::number(pkt._pktSendId) << QString::number(pkt._pktFileId) << QString::number(nowSize);emit UpdateAcceptUIProgress(list);//刷新UI的百分比//发送DATA_OK;}if(file.isOpen())file.close();
还有就是在写文件的时候 因为太快了所以会导致包发送的时候会丢失 这个时候你可以选择在Write之前选择延时 也可以选择使用QT的waitforReadyRead waitForBytesWritten等函数进行处理
void PubFunction::Sleep(unsigned int msec)
{QTime _Timer = QTime::currentTime().addMSecs(msec);while( QTime::currentTime() < _Timer )QCoreApplication::processEvents(QEventLoop::AllEvents, 100);
}if(_fileDataPktMap.contains(pkt._pktFileId))
{QList<FILE_DATA_PKT> pktList = _fileDataPktMap[pkt._pktFileId];qDebug() << pktList.size();for(auto& pkt : pktList){this->Write((char*)&pkt,sizeof(FILE_DATA_PKT));PubFunction::Sleep(30);}
}
三、总结
其他都都是比较常规的吧 难点我个人认为已经标记出来了 还有一些逻辑我觉得应该也说了 如果还有问题可以提出来 谢谢大家
总结一下 我永远喜欢慧慧-。-
本文来自互联网用户投稿,文章观点仅代表作者本人,不代表本站立场,不承担相关法律责任。如若转载,请注明出处。 如若内容造成侵权/违法违规/事实不符,请点击【内容举报】进行投诉反馈!
