QGraphicsView 实例3地图浏览器

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

效果图:

mapwidget.h

cpp 复制代码
#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

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;
}
相关推荐
用户805533698031 天前
不止三件套:QObject 属性系统全关键字与运行时反射!
c++·qt
xcyxiner1 天前
DicomViewer (vcpkg Windows和ubuntu编译)7
qt
Quz6 天前
QML Hello World 入门示例
qt
xcyxiner10 天前
DicomViewer (dcmtk读取dcm文件)5
qt
xcyxiner10 天前
DicomViewer (后台线程处理文件)4
qt
xcyxiner10 天前
DicomViewer (添加模型类)3
qt
xcyxiner11 天前
DicomViewer (目录调整) 2
qt
xcyxiner11 天前
dcmtk vtk vtk-dicom(gdcm) 编译(debug) v2
qt
LDR00613 天前
Type-C 快充全面升级!LDR6601 赋能个人护理便携电机,重塑剃须刀 / 理发器新体验
c语言·开发语言
雪碧聊技术13 天前
Tree.js是什么?一文讲透
开发语言·javascript·ecmascript