












之前web版本的地图组件,有一些用户反馈说加载瓦片的时候,能够看到明显的加载过程,比如先是一个空白的白色正方形区域,然后才是一张瓦片图片加载后绘制在对应区域,在拖动地图的时候,更明显,总体体验不是很好,如果该图片是首次加载,还能够理解,毕竟需要经过下载再绘制,是需要时间的,而当之前已经下载的,如果还出现空白再绘制,就无法接收,是否可以直接从内存中直接取出图片文件绘制,按照这个思路,纯qwidget版本的地图组件,内部维护一个缓存图片队列,当需要绘制的时候,先从缓存队列查询是否存在这个图片,存在则直接取出来,不存在再去下载,这样体验有了很好的提升,只有首次绘制的时候会看到过渡效果。
联网下载瓦片,相比直接从本地硬盘上取出图片,速度更慢,所以后面还加上了缓存文件的功能,也就是将下载的瓦片文件缓存在本地盘符,这样可以省去再去下载的过程,节约流量,于是整个加载流程就变成了下面的。

#include "imagedownload.h"
namespace qmapcontrol {
ImageDownload::ImageDownload(QObject *parent) : QObject(parent)
{
QObject::connect(&m_network_access_manager, SIGNAL(finished(QNetworkReply *)), this, SLOT(downloadFinished(QNetworkReply *)));
}
ImageDownload::~ImageDownload()
{
this->abortDownloads();
}
void ImageDownload::abortDownloads()
{
//释放等待中的请求
QMutexLocker lock(&m_mutex_downloading_image);
foreach (QNetworkReply *reply, m_downloading_reply) {
reply->abort();
}
//清空下载队列
m_downloading_url.clear();
m_downloading_reply.clear();
}
int ImageDownload::downloadQueueSize() const
{
QMutexLocker lock(&m_mutex_downloading_image);
return m_downloading_reply.size();
}
bool ImageDownload::isDownloading(const QUrl &url) const
{
QMutexLocker lock(&m_mutex_downloading_image);
return m_downloading_url.contains(url);
}
void ImageDownload::downloadImage(const QUrl &url)
{
//没有处于下载中的则启动下载
QMutexLocker lock(&m_mutex_downloading_image);
if (!m_downloading_url.contains(url)) {
QNetworkRequest request(url);
QNetworkReply *reply = m_network_access_manager.get(request);
m_downloading_url << url;
m_downloading_reply << reply;
}
}
void ImageDownload::downloadFinished(QNetworkReply *reply)
{
if (reply->error() != QNetworkReply::NoError) {
//qDebug() << TIMEMS << "Download faile" << reply->url() << reply->errorString();
} else {
QMutexLocker lock(&m_mutex_downloading_image);
int index = m_downloading_reply.indexOf(reply);
if (index >= 0) {
QImageReader image_reader(reply);
QPixmap pixmap = QPixmap::fromImageReader(&image_reader);
emit imageDownloaded(reply->url(), pixmap);
m_downloading_url.removeAt(index);
m_downloading_reply.removeAt(index);
}
}
//每次判断下是不是全部下载完成了
if (reply->error() != QNetworkReply::OperationCanceledError) {
if (downloadQueueSize() == 0) {
emit downloadingFinished();
}
}
//释放对象
reply->deleteLater();
}
}
此内容由惯性聚合(RSS阅读器)自动聚合整理,仅供阅读参考。 原文来自 — 版权归原作者所有。