QGraphicsView 实例3地图浏览器

主要介绍Graphics View框架,实现地图的浏览、放大、缩小,以及显示各个位置的视图、场景和地图坐标

效果图:

QGraphicsView 实例3地图浏览器_第1张图片

 mapwidget.h

#ifndef MAPWIDGET_H
#define MAPWIDGET_H
#include 
#include 
#include 

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 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 


/* 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;
}

你可能感兴趣的:(开发语言,qt)