主要介紹Graphics View框架,實現地圖的瀏覽、放大、縮小,以及顯示各個位置的視圖、場景和地圖坐標
效果圖:
?mapwidget.h
#ifndef MAPWIDGET_H
#define MAPWIDGET_H
#include <QLabel>
#include <QMouseEvent>
#include <QGraphicsView>class MapWidget : public QGraphicsView
{
public:MapWidget();void readMap();QPointF mapToMap(QPointF); //實現場景坐標系與地圖坐標之間的映射,以獲得某點的經緯度值public slots:void slotZoom(int);QPixmap map;
protected:void drawBackground(QPainter *painter,const QRectF &rect); //完成地圖顯示的功能void mouseMoveEvent(QMouseEvent * event);private:qreal zoom;QLabel *viewCoord;QLabel *sceneCoord;QLabel *mapCoord;double x1,x2;double y1,y2;};#endif // MAPWIDGET_H
?mapwidget.cpp
#include "mapwidget.h"
#include <QSlider>
#include <QGridLayout>
#include <QVBoxLayout>
#include <QHBoxLayout>
#include <QFile>
#include <QGraphicsScene>
#include <QTextStream>
#include <math.h>
#include <QLabel>/* 1、setCacheMode(CacheBackground)這個屬性控制view的那一部分緩存中,QGraphicsView可以預存一些內容在QPixmap中,
* 然后被繪制到viewpoint上,這樣做的目的是加速整體區域重繪的速度,例如:質地、傾斜度、和最初的混合背景可能重繪很緩慢,
* 尤其是在一個變形的view中,CacheBackground標志使能view的背景緩存,例如
* QGraphicsView view;
* view.setBackgroundBrush(QImage(":/images/backgroundtile.png"));
* view.setCacheMode(QGraphicsView::CacheBackground);
* 每次view轉換后cache就無效了,然而,當滾動區域時候,只有部分無效默認的,沒有使用cache
* 2、setTickInterval(int)來設置發射信號的間隔,一般都設置為1000ms,就是1s發射一次
* 3、setScaledContents(bool)這個屬性保存標簽是否按這個圖片的比例填滿所用的可用空間,默認false*/MapWidget::MapWidget()
{//讀取地圖信息,包括地圖的名稱,經緯度等readMap();zoom=50;int width=map.width();int height=map.height();QGraphicsScene *scene=new QGraphicsScene(this);scene->setSceneRect(-width/2,-height/2,width,height);setScene(scene);setCacheMode(CacheBackground);//用于地圖縮放的滑動條QSlider *slider=new QSlider;slider->setOrientation(Qt::Vertical);slider->setRange(1,100);slider->setTickInterval(10);slider->setValue(1);connect(slider,&QSlider::valueChanged,[=](int t_value){slotZoom(t_value);});;QLabel *zoomin=new QLabel;zoomin->setScaledContents(true);zoomin->setPixmap(QPixmap(":/image/zoomin.jpg"));zoomin->setFixedSize(30,30);QLabel *zoomout=new QLabel;zoomout->setScaledContents(true );zoomout->setPixmap(QPixmap(":/image/zoomout.jpg"));zoomout->setFixedSize(30,30);//坐標值顯示區QLabel *label1=new QLabel(QStringLiteral("QGraphicsView:"));viewCoord=new QLabel;QLabel *label2=new QLabel(QStringLiteral("QGraphicsScene:"));sceneCoord=new QLabel;QLabel *label3=new QLabel(QStringLiteral("map:"));mapCoord=new QLabel;//坐標顯示區布局QGridLayout *gridLayout=new QGridLayout;gridLayout->addWidget(label1,0,0);gridLayout->addWidget(viewCoord,0,1);gridLayout->addWidget(label2,1,0);gridLayout->addWidget(sceneCoord,1,1);gridLayout->addWidget(label3,2,0);gridLayout->addWidget(mapCoord,2,1);gridLayout->setSizeConstraint(QLayout::SetFixedSize);QFrame *coordFrame=new QFrame;coordFrame->setLayout(gridLayout);//坐標顯示布局QVBoxLayout *coordLayout=new QVBoxLayout;coordLayout->addWidget(coordFrame);coordLayout->addStretch();//縮放控制子布局QVBoxLayout *zoomlayout=new QVBoxLayout;zoomlayout->addWidget(zoomin);zoomlayout->addWidget(slider);zoomlayout->addWidget(zoomout);//主布局QHBoxLayout *mainLayout = new QHBoxLayout;mainLayout->addLayout(zoomlayout);mainLayout->addLayout(coordLayout);mainLayout->addStretch();mainLayout->setMargin(30);mainLayout->setSpacing(10);setLayout(mainLayout);setWindowTitle(QStringLiteral("Map Widget"));setMinimumSize(600,400);}
void MapWidget::readMap() //讀取地圖信息
{QString mapName;QFile mapFile(":/image/China.txt");int ok=mapFile.open((QIODevice::ReadOnly | QIODevice::Text)); //以"只讀"方式打開此文件if(ok){QTextStream ts(&mapFile);if(!ts.atEnd()){ts >> mapName;ts>>x1>>y1>>x2>>y2;}}mapFile.close();map.load(":/image/China.jpg"); //將地圖讀取至私有變量map中}//根據縮放滑動條的當前值,確定當前縮放的比例
void MapWidget::slotZoom(int value)
{/** 檢測value(slider改變得到的值),與當前value值得大小比較* pow(x, y)表示x的y次方* slider改變的值大于zoom值時,增加縮放比例* slider改變的值小于zoom值時,減小縮放比例* scale(s, s)將當前的視圖換為(s, s)*/qreal s;if(value>zoom) //放大{s=pow(1.01,(value-zoom));}else{s=pow(1/1.01,(zoom-value));}scale(s,s); //實現地圖的縮放zoom=value;}//以地圖圖片重繪場景的背景來實現地圖顯示
void MapWidget::drawBackground(QPainter *painter, const QRectF &rect)
{painter->drawPixmap(int(sceneRect().left()),int(sceneRect().top()),map);
}//完成某點在坐標上的映射和顯示
void MapWidget::mouseMoveEvent(QMouseEvent *event)
{//QGraphicsView坐標QPoint viewpoint=event->pos();viewCoord->setText(QString::number(viewpoint.x())+","+QString::number(viewpoint.y()));//QGraphicsScene坐標QPointF scenePoint=mapToScene(viewpoint);sceneCoord->setText(QString::number(scenePoint.x())+","+QString::number(scenePoint.y()));//地圖坐標(經緯度)QPointF latLon= mapToMap(scenePoint);mapCoord->setText(QString::number(latLon.x())+","+QString::number(latLon.y()));}QPointF MapWidget::mapToMap(QPointF p)
{QPointF latLon;qreal w=sceneRect().width();qreal h=sceneRect().height();qreal lon=y1-((h/2+p.y())*abs(y1-y2)/h);qreal lat=y1-((w/2+p.x())*abs(x1-x2)/w);latLon.setX(lat);latLon.setY(lon);return latLon;
}