QT_地图导航 源码下载
https://github.com/douzujun/MyMapView
主要算法讲解:
1. 计算最短路径(dijkstra算法)
Step1:
(1)找到最短路径已经确定的顶点,从它已经确定的顶点,从它除法更新相邻顶点的最短距离。
(2)此后不需要再关心1中的“最短距离已经确定的顶点”。
(3)在(1)和(2)中提到的“最短距离已经确定的顶点”要求解的关键。在最开始时,只有起点的最短距离是确定的。而在尚未使用过的顶点中,距离d[i]最小的顶点就是最短距离已经确定的顶点。这是因为由于不存在负边,所以d[i]不会在更新中变小。
定义几个方便算法描述的变量:
int cost[MAX_V][MAX_V]; //cost[u][v]表示表e=(u,v)的权值(不存在这条边时设为INF)
int d[MAX_V]; //顶点s出发的最短路径
bool used[MAX_V]; //已经使用的图
Step2:
(1)如果,我们需要输出最短路的路径。注,在求解最短路径时,满足d[j] = d[k] + cost[k][j]的顶点k(d[j]是表示从起点开始到j的最短路径距离,cost[k][j]是表示k到j的距离),就是最短路上的顶点j的前驱结点,因此通过不断寻找前驱结点就可以恢复最短路。时间复杂度是O(E)。
(2)如果,我们用prev[j]来记录最短路上的顶点j的前驱,那么就可以在O(|V|)时间内完成最短路的恢复。在d[j]=d[k]+cost[k][j]更新时,修改prev[j]=k, 这样就可以求得prev数组。在计算从起点s出发到j的最短路时,通过prev[j]就可以知道顶点j的前驱,因此不断把j替换成prev[j]直到j = s为止即可。代码如下:
1. 首先要对图进行初始化,才能正常计算最短路径
MainWindow::DijkstraFindPath::DijkstraFindPath()
{
mgraph.vexnum = ; //初始化点数目
for (int i = ; i < mgraph.vexnum; i++) //初始化点编号
mgraph.vexs.push_back (i);
mgraph.arcnum = ; //边数
for (int i = ; i < mgraph.vexnum; i++) {
for (int j = ; j < mgraph.vexnum; j++) {
if (i == j)
mgraph.arcs[i][j].adj = ;
else
mgraph.arcs[i][j].adj = INF;
}
}
}
2. 设置图的景点之间的权值。
void MainWindow::DijkstraFindPath::CreateGraph ()
{
mgraph.arcs[][].adj = mgraph.arcs[][].adj = ; //6 - 5
mgraph.arcs[][].adj = mgraph.arcs[][].adj = ; //6 - 10
mgraph.arcs[][].adj = mgraph.arcs[][].adj = ; //5 - 4
mgraph.arcs[][].adj = mgraph.arcs[][].adj = ; //4 - 3
mgraph.arcs[][].adj = mgraph.arcs[][].adj = ; //3 - 2
mgraph.arcs[][].adj = mgraph.arcs[][].adj = ; //3 - 22
mgraph.arcs[][].adj = mgraph.arcs[][].adj = ; //2 - 1
mgraph.arcs[][].adj = mgraph.arcs[][].adj = ;//23 - 22
mgraph.arcs[][].adj = mgraph.arcs[][].adj = ; //6 - 23
mgraph.arcs[][].adj = mgraph.arcs[][].adj = ; //23 - 4
mgraph.arcs[][].adj = mgraph.arcs[][].adj = ; //1 - 一食堂
mgraph.arcs[][].adj = mgraph.arcs[][].adj = ;//一食堂-操场
mgraph.arcs[][].adj = mgraph.arcs[][].adj = ;//一食堂-祁通1
mgraph.arcs[][].adj = mgraph.arcs[][].adj = ;//祁通1-祁通2(路口)
mgraph.arcs[][].adj = mgraph.arcs[][].adj = ; //一食堂-岔路口
mgraph.arcs[][].adj = mgraph.arcs[][].adj = ;//一食堂到岔路(通向7号楼的)
mgraph.arcs[][].adj = mgraph.arcs[][].adj = ;//岔路-祁通大道
mgraph.arcs[][].adj = mgraph.arcs[][].adj = ;//祁通大道-图书馆
mgraph.arcs[][].adj = mgraph.arcs[][].adj = ;//祁通大道-祁通2
mgraph.arcs[][].adj = mgraph.arcs[][].adj = ;//祁通2-方肇周
mgraph.arcs[][].adj = mgraph.arcs[][].adj = ;//西大门-祁通1
mgraph.arcs[][].adj = mgraph.arcs[][].adj = ; //祁通1-祁通2
mgraph.arcs[][].adj = mgraph.arcs[][].adj = ; //1 - 操场
mgraph.arcs[][].adj = mgraph.arcs[][].adj = ; //10 - 9
mgraph.arcs[][].adj = mgraph.arcs[][].adj = ; //9 - 8
mgraph.arcs[][].adj = mgraph.arcs[][].adj = ; //8 - 7
mgraph.arcs[][].adj = mgraph.arcs[][].adj = ; //7 - 图书馆
mgraph.arcs[][].adj = mgraph.arcs[][].adj = ; //10 - 13
mgraph.arcs[][].adj = mgraph.arcs[][].adj = ;//13 - 12
mgraph.arcs[][].adj = mgraph.arcs[][].adj = ;//13 - 16
mgraph.arcs[][].adj = mgraph.arcs[][].adj = ;//12 - 15
mgraph.arcs[][].adj = mgraph.arcs[][].adj = ;//16 - 15
mgraph.arcs[][].adj = mgraph.arcs[][].adj = ;//15 - 14
mgraph.arcs[][].adj = mgraph.arcs[][].adj = ;//16 - 19
mgraph.arcs[][].adj = mgraph.arcs[][].adj = ; //19 - 18
mgraph.arcs[][].adj = mgraph.arcs[][].adj = ; //18 - 17
mgraph.arcs[][].adj = mgraph.arcs[][].adj = ;//14 - 17
mgraph.arcs[][].adj = mgraph.arcs[][].adj = ; //17 - 二超
mgraph.arcs[][].adj = mgraph.arcs[][].adj = ; //二超 - 二食堂 //以下处理细节—这是景点之间的一小段路之间的权值,因为用界面绘制路线,会//出现弧状的路线,所以需要定额外的坐标
mgraph.arcs[][].adj = mgraph.arcs[][].adj = ; //祁通大道-祁通大道2
mgraph.arcs[][].adj = mgraph.arcs[][].adj = ; //祁通大道2-祁通大道3
mgraph.arcs[][].adj = mgraph.arcs[][].adj = ; //祁通大道3-图书馆
mgraph.arcs[][].adj = mgraph.arcs[][].adj = ; //图书馆-祁通大道4
mgraph.arcs[][].adj = mgraph.arcs[][].adj = ; //祁通4-祁通5
mgraph.arcs[][].adj = mgraph.arcs[][].adj = ; //祁通5-二食堂
mgraph.arcs[][].adj = mgraph.arcs[][].adj = ; //祁通5-二超
mgraph.arcs[][].adj = mgraph.arcs[][].adj = ; //祁通4-通向14号楼的小道
mgraph.arcs[][].adj = mgraph.arcs[][].adj = ; //小道-14号楼
mgraph.arcs[][].adj = mgraph.arcs[][].adj = ; //小道14-小道15
mgraph.arcs[][].adj = mgraph.arcs[][].adj = ; //小道15-15
mgraph.arcs[][].adj = mgraph.arcs[][].adj = ; //小道15-12
mgraph.arcs[][].adj = mgraph.arcs[][].adj = ; //岔路-岔路2
mgraph.arcs[][].adj = mgraph.arcs[][].adj = ; //岔路2-7 }
3. 计算最短路径,并对输出路径进行初始化工作。
void MainWindow::DijkstraFindPath::dijkstra (int startPos)
{
for (int i = ; i < mgraph.vexnum; i++) d[i] = INF;
for (int i = ; i < mgraph.vexnum; i++) used[i] = false;
for (int i = ; i < mgraph.vexnum; i++) prev[i] = -;
d[startPos] = ; while (true) {
int v = -;
for (int u = ; u < mgraph.vexnum; u++) {
if (!used[u] && (v == - || d[u] < d[v])) v = u;
} if (v == -) break;
used[v] = true; for (int u = ; u < mgraph.vexnum; u++) {
if (d[u] > d[v] + mgraph.arcs[v][u].adj) {
d[u] = d[v] + mgraph.arcs[v][u].adj;
prev[u] = v;
}
}
}
}
4.存储起点到终点之间的路径。
QVector<int> MainWindow::DijkstraFindPath::get_Path (int endPos)
{
QVector<int> path;
//保存景点之间的最短路径上的全部景点
for ( ; endPos != -; endPos = prev[endPos]) {
path.push_back (endPos);
}
//由于路径是从终点向起点保存的,还需要将路径逆置。
std::reverse(path.begin (), path.end ());
return path;
}
全部代码:
1 首先要对图进行初始化,才能正常计算最短路径
/**
* 主要功能:
* 1. 绘制输入起点,终点最短路径
* 2. 双击地点, 查看景点信息
* 3. 修改景点图片
* 4. 打开测试地图,查看地图坐标,可缩放地图.
**/
#ifndef MAINWINDOW_H
#define MAINWINDOW_H #include <QMainWindow>
#include "mapwidget.h"
#include <QToolButton>
#include <QGraphicsLineItem>
#include <QGraphicsScene>
#include <QGraphicsView>
#include <QLabel>
#include <QComboBox>
#include <QTextEdit>
#include <QVector>
#include <QMouseEvent>
#include <QDialog>
#include <QPixmap>
#include <QGridLayout>
#include <QLineEdit>
#include <QFileDialog>
#include <QHBoxLayout> class MainWindow : public QMainWindow
{
Q_OBJECT
public:
MainWindow(QWidget *parent = );
~MainWindow();
void createToolBar();
void createAction();
void setStart(int X, int Y);
void setEnd(int X, int Y);
void setNextPos (int index);
void initScene();
public slots:
void setStartStation();
void setEndStation();
void FindPath();
void Clear();
void Revise();
void callOtherMap();
void ShowDialog();
private:
MapWidget *mapWidget;
QLabel *startLabel;
QLabel *endLabel;
QComboBox *startComboBox;
QComboBox *endComboBox;
QComboBox *reviseComboBox; QAction *findPathAction;
QAction *clearAction;
QAction *reviseAction;
QAction *callMap; QGraphicsScene *scene;
QGraphicsView *view; int startX, startY, endX, endY;
QVector<int> nextPath; /*
* 图的实现,和最短路径算法声明
*/
struct ArcCell{ //弧信息
int adj; //对无权图有1,0表示是否相邻,对带权图,则为权值类型
// string info; //该弧的相关信息
}; //内部类
static const int MAX_VERTEX_NUM = ;
static const int INF = ; struct MGraph{
QVector<int> vexs; //顶点集合
//临接矩阵
ArcCell arcs[MAX_VERTEX_NUM][MAX_VERTEX_NUM];
int vexnum; //顶点数
int arcnum; //边数
// int kind; //图的类型
}; class DijkstraFindPath
{
public:
DijkstraFindPath();
MGraph mgraph;
void CreateGraph(); int prev[MAX_VERTEX_NUM]; //最短路上的前驱顶点
int d[MAX_VERTEX_NUM]; //表示边e = (u,v)的权值(不存在时为INF,不过d[i][i]=0)
bool used[MAX_VERTEX_NUM]; //已经使用过的图
void dijkstra(int startPos); //求从起点startPos出发到各个顶点的最短距离
QVector<int> get_Path(int endPos);//到顶点endPos的最短路
}; DijkstraFindPath *dj; //鼠标事件
protected:
void mouseDoubleClickEvent (QMouseEvent *e);
private:
QPixmap library; //图书馆
QPixmap canteen; //餐厅
QPixmap jxjBuilding; //计算机楼
QPixmap westgate; //西门
QPixmap westground; //西操
QPixmap twoMarket; //二超
QString strPath; //文件路径
QLabel *label;
}; #endif // MAINWINDOW_H
#include "mainwindow.h"
#include <qdebug.h>
#include <QToolBar>
#include <QtAlgorithms>
#include <iostream>
#include <windows.h> MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent)
{
setWindowTitle ("可爱的豆豆豆 校园导航");
dj = new MainWindow::DijkstraFindPath();
dj->CreateGraph (); scene = new QGraphicsScene;
scene->setSceneRect (-, -, , );
initScene(); view = new QGraphicsView;
view->setScene (scene);
view->setMinimumSize (, );
view->show ();
setCentralWidget (view); createAction ();
createToolBar (); //实现一个工具栏
setMinimumSize (, ); //设置最小尺寸
Sleep();
} MainWindow::DijkstraFindPath::DijkstraFindPath()
{
mgraph.vexnum = ; //初始化点数目
for (int i = ; i < mgraph.vexnum; i++) //初始化点编号
mgraph.vexs.push_back (i);
mgraph.arcnum = ; //暂定
for (int i = ; i < mgraph.vexnum; i++) {
for (int j = ; j < mgraph.vexnum; j++) {
if (i == j)
mgraph.arcs[i][j].adj = ;
else
mgraph.arcs[i][j].adj = INF;
// mgraph.arcs[i][j].info = "";
}
}
} void MainWindow::DijkstraFindPath::CreateGraph ()
{
mgraph.arcs[][].adj = mgraph.arcs[][].adj = ; //6 - 5
mgraph.arcs[][].adj = mgraph.arcs[][].adj = ; //6 - 10
mgraph.arcs[][].adj = mgraph.arcs[][].adj = ; //5 - 4
mgraph.arcs[][].adj = mgraph.arcs[][].adj = ; //4 - 3
mgraph.arcs[][].adj = mgraph.arcs[][].adj = ; //3 - 2
mgraph.arcs[][].adj = mgraph.arcs[][].adj = ; //3 - 22
mgraph.arcs[][].adj = mgraph.arcs[][].adj = ; //2 - 1
mgraph.arcs[][].adj = mgraph.arcs[][].adj = ;//23 - 22
mgraph.arcs[][].adj = mgraph.arcs[][].adj = ; //6 - 23
mgraph.arcs[][].adj = mgraph.arcs[][].adj = ; //23 - 4
mgraph.arcs[][].adj = mgraph.arcs[][].adj = ; //1 - 一食堂
mgraph.arcs[][].adj = mgraph.arcs[][].adj = ;//一食堂-操场
mgraph.arcs[][].adj = mgraph.arcs[][].adj = ;//一食堂-祁通1
mgraph.arcs[][].adj = mgraph.arcs[][].adj = ;//祁通1-祁通2(路口)
mgraph.arcs[][].adj = mgraph.arcs[][].adj = ; //一食堂-岔路口
// mgraph.arcs[29][9].adj = mgraph.arcs[9][29].adj = 80; //岔路-7
mgraph.arcs[][].adj = mgraph.arcs[][].adj = ;//一食堂到岔路(通向7号楼的)
mgraph.arcs[][].adj = mgraph.arcs[][].adj = ;//岔路-祁通大道
mgraph.arcs[][].adj = mgraph.arcs[][].adj = ;//祁通大道-图书馆
mgraph.arcs[][].adj = mgraph.arcs[][].adj = ;//祁通大道-祁通2
mgraph.arcs[][].adj = mgraph.arcs[][].adj = ;//祁通2-方肇周
mgraph.arcs[][].adj = mgraph.arcs[][].adj = ; //西大门-祁通1
mgraph.arcs[][].adj = mgraph.arcs[][].adj = ; //祁通1-祁通2
mgraph.arcs[][].adj = mgraph.arcs[][].adj = ; //1 - 操场
mgraph.arcs[][].adj = mgraph.arcs[][].adj = ; //10 - 9
mgraph.arcs[][].adj = mgraph.arcs[][].adj = ; //9 - 8
mgraph.arcs[][].adj = mgraph.arcs[][].adj = ; //8 - 7
mgraph.arcs[][].adj = mgraph.arcs[][].adj = ; //7 - 图书馆
mgraph.arcs[][].adj = mgraph.arcs[][].adj = ; //10 - 13
mgraph.arcs[][].adj = mgraph.arcs[][].adj = ;//13 - 12
mgraph.arcs[][].adj = mgraph.arcs[][].adj = ;//13 - 16
mgraph.arcs[][].adj = mgraph.arcs[][].adj = ;//12 - 15
mgraph.arcs[][].adj = mgraph.arcs[][].adj = ;//16 - 15
mgraph.arcs[][].adj = mgraph.arcs[][].adj = ;//15 - 14
mgraph.arcs[][].adj = mgraph.arcs[][].adj = ;//16 - 19
mgraph.arcs[][].adj = mgraph.arcs[][].adj = ; //19 - 18
mgraph.arcs[][].adj = mgraph.arcs[][].adj = ; //18 - 17
mgraph.arcs[][].adj = mgraph.arcs[][].adj = ;//14 - 17
mgraph.arcs[][].adj = mgraph.arcs[][].adj = ; //17 - 二超
mgraph.arcs[][].adj = mgraph.arcs[][].adj = ; //二超 - 二食堂
// mgraph.arcs[24][10].adj = mgraph.arcs[10][24].adj = 260;//二食堂-图书馆 //以下处理细节
mgraph.arcs[][].adj = mgraph.arcs[][].adj = ; //祁通大道-祁通大道2
mgraph.arcs[][].adj = mgraph.arcs[][].adj = ; //祁通大道2-祁通大道3
mgraph.arcs[][].adj = mgraph.arcs[][].adj = ; //祁通大道3-图书馆
mgraph.arcs[][].adj = mgraph.arcs[][].adj = ; //图书馆-祁通大道4
mgraph.arcs[][].adj = mgraph.arcs[][].adj = ; //祁通4-祁通5
mgraph.arcs[][].adj = mgraph.arcs[][].adj = ; //祁通5-二食堂
mgraph.arcs[][].adj = mgraph.arcs[][].adj = ; //祁通5-二超
mgraph.arcs[][].adj = mgraph.arcs[][].adj = ; //祁通4-通向14号楼的小道
mgraph.arcs[][].adj = mgraph.arcs[][].adj = ; //小道-14号楼
mgraph.arcs[][].adj = mgraph.arcs[][].adj = ; //小道14-小道15
mgraph.arcs[][].adj = mgraph.arcs[][].adj = ; //小道15-15
mgraph.arcs[][].adj = mgraph.arcs[][].adj = ; //小道15-12
mgraph.arcs[][].adj = mgraph.arcs[][].adj = ; //岔路-岔路2
mgraph.arcs[][].adj = mgraph.arcs[][].adj = ; //岔路2-7 } void MainWindow::DijkstraFindPath::dijkstra (int startPos)
{
for (int i = ; i < mgraph.vexnum; i++) d[i] = INF;
for (int i = ; i < mgraph.vexnum; i++) used[i] = false;
for (int i = ; i < mgraph.vexnum; i++) prev[i] = -;
d[startPos] = ; while (true) {
int v = -;
for (int u = ; u < mgraph.vexnum; u++) {
if (!used[u] && (v == - || d[u] < d[v])) v = u;
} if (v == -) break;
used[v] = true; for (int u = ; u < mgraph.vexnum; u++) {
if (d[u] > d[v] + mgraph.arcs[v][u].adj) {
d[u] = d[v] + mgraph.arcs[v][u].adj;
prev[u] = v;
}
}
}
} QVector<int> MainWindow::DijkstraFindPath::get_Path (int endPos)
{
QVector<int> path; for ( ; endPos != -; endPos = prev[endPos]) {
// std::cout << "EndPos: " << endPos << ", ";
path.push_back (endPos);
} std::reverse(path.begin (), path.end ()); return path;
} void MainWindow::initScene ()
{
QGraphicsPixmapItem *item =
scene->addPixmap (QPixmap("NanTong.jpg"));
// item->setFlag (QGraphicsItem::ItemIsMovable);
item->setPos (-, -);
} MainWindow::~MainWindow()
{ } void MainWindow::createAction ()
{
findPathAction = new QAction(QIcon("Search.png"),tr("搜索路径"), this);
findPathAction->setShortcut (tr("Ctrl+F"));
findPathAction->setStatusTip (tr("搜索路径"));
connect (findPathAction, SIGNAL(triggered(bool)), this, SLOT(FindPath())); clearAction = new QAction(QIcon("Clear.png"), tr("清理路径"), this);
clearAction->setShortcut (tr("Ctrl+W"));
clearAction->setStatusTip (tr("清理路径"));
connect (clearAction, SIGNAL(triggered(bool)), this, SLOT(Clear())); reviseAction = new QAction(QIcon("revise.png"), tr("修改景点"), this);
reviseAction->setShortcut (tr("Ctrl+R"));
clearAction->setStatusTip (tr("修改景点"));
connect (reviseAction, SIGNAL(triggered(bool)), this, SLOT(Revise())); callMap = new QAction(QIcon("map.png"), tr("调用测试地图"), this);
callMap->setShortcut (tr("Ctrl+M"));
callMap->setStatusTip (tr("调用测试地图"));
connect (callMap, SIGNAL(triggered(bool)), this, SLOT(callOtherMap())); } void MainWindow::createToolBar ()
{
QToolBar *toolBar = addToolBar ("Tool");
startLabel = new QLabel(tr("起点: "));
startComboBox = new QComboBox;
startComboBox->addItem (tr("公寓6号楼")); //
startComboBox->addItem (tr("公寓5号楼")); //
startComboBox->addItem (tr("公寓4号楼")); //
startComboBox->addItem (tr("公寓3号楼")); //
startComboBox->addItem (tr("公寓2号楼")); //
startComboBox->addItem (tr("公寓1号楼")); // startComboBox->addItem (tr("公寓10号楼")); //
startComboBox->addItem (tr("公寓9号楼")); //
startComboBox->addItem (tr("公寓8号楼")); //
startComboBox->addItem (tr("公寓7号楼")); //
startComboBox->addItem (tr("图书馆")); //
startComboBox->addItem (tr("一食堂")); startComboBox->addItem (tr("西操场")); //11 12
startComboBox->addItem (tr("公寓23号楼")); startComboBox->addItem (tr("公寓13号楼")); //13 14
startComboBox->addItem (tr("公寓22号楼")); startComboBox->addItem (tr("公寓12号楼")); //15 16
startComboBox->addItem (tr("公寓楼16")); startComboBox->addItem (tr("公寓楼15")); //17 18
startComboBox->addItem (tr("公寓楼14")); startComboBox->addItem (tr("公寓楼19")); //19 20
startComboBox->addItem (tr("公寓楼18")); startComboBox->addItem (tr("公寓楼17")); //21 22
startComboBox->addItem (tr("二超")); startComboBox->addItem (tr("二食堂")); //23 24
startComboBox->addItem (tr("西大门")); startComboBox->addItem (tr("方肇周教学楼")); //25 26 endLabel = new QLabel(tr("终点: ")); endComboBox = new QComboBox;
endComboBox->addItem (tr("公寓6号楼"));
endComboBox->addItem (tr("公寓5号楼"));
endComboBox->addItem (tr("公寓4号楼"));
endComboBox->addItem (tr("公寓3号楼"));
endComboBox->addItem (tr("公寓2号楼"));
endComboBox->addItem (tr("公寓1号楼"));
endComboBox->addItem (tr("公寓10号楼"));
endComboBox->addItem (tr("公寓9号楼"));
endComboBox->addItem (tr("公寓8号楼"));
endComboBox->addItem (tr("公寓7号楼"));
endComboBox->addItem (tr("图书馆"));
endComboBox->addItem (tr("一食堂")); endComboBox->addItem (tr("西操场"));
endComboBox->addItem (tr("公寓23号楼"));endComboBox->addItem (tr("公寓13号楼"));
endComboBox->addItem (tr("公寓22号楼"));endComboBox->addItem (tr("公寓12号楼"));
endComboBox->addItem (tr("公寓楼16")); endComboBox->addItem (tr("公寓楼15"));
endComboBox->addItem (tr("公寓楼14")); endComboBox->addItem (tr("公寓楼19"));
endComboBox->addItem (tr("公寓楼18")); endComboBox->addItem (tr("公寓楼17"));
endComboBox->addItem (tr("二超")); endComboBox->addItem (tr("二食堂"));
endComboBox->addItem (tr("西大门")); endComboBox->addItem (tr("方肇周教学楼")); connect (startComboBox, SIGNAL(activated(int)), this, SLOT(setStartStation()));
connect (endComboBox, SIGNAL(activated(int)), this, SLOT(setEndStation())); toolBar->addWidget (startLabel);
toolBar->addWidget (startComboBox);
toolBar->addSeparator ();
toolBar->addWidget (endLabel);
toolBar->addWidget (endComboBox);
toolBar->addSeparator ();
toolBar->addAction(findPathAction);
toolBar->addSeparator ();
toolBar->addAction(clearAction);
toolBar->addSeparator ();
toolBar->addAction(reviseAction);
toolBar->addSeparator ();
toolBar->addAction(callMap); } void MainWindow::setStart(int X, int Y) {
startX = X; startY = Y;
// qDebug() << X << ", " << Y;
} void MainWindow::setEnd (int X, int Y)
{
endX = X; endY = Y;
} void MainWindow::setStartStation ()
{
switch (startComboBox->currentIndex ()) {
case :
setStart(-, -); break;
case :
setStart (-, -); break;
case :
setStart (-, -); break;
case :
setStart (-, -); break;
case :
setStart (-, -); break;
case :
setStart (-, -); break;
case :
setStart (-, -); break;
case :
setStart (-, -); break;
case :
setStart(-, -); break;
case :
setStart (-, -); break;
case :
setStart (-, -); break;
case :
setStart (-, -); break;
case :
setStart (-, -); break;
case :
setStart (-, -); break;
case :
setStart (-, -); break;
case :
setStart (-, -); break;
case :
setStart (-, -); break;
case :
setStart (-, -); break;
case :
setStart (-, -); break;
case :
setStart (-, -); break;
case :
setStart (-, -); break;
case :
setStart (-, -); break;
case :
setStart (-, -); break;
case :
setStart (-, -); break;
case :
setStart (-, -); break;
case :
setStart (-, -); break;
case :
setStart (-, -); break;
case :
setStart (-, -); break;
case :
setStart (-, -); break;
case :
setStart (-, -); break;
case :
setStart (-, -); break;
case :
setStart (-, -); break;
case :
setStart (-, -); break;
case :
setStart (-, -); break;
case :
setStart (-, -); break;
case :
setStart (-, -); break;
case :
setStart (-, -); break;
case :
setStart (-, -); break;
default:
break;
}
} void MainWindow::setEndStation ()
{
switch (endComboBox->currentIndex ()) {
case :
setEnd(-, -); break;
case :
setEnd (-, -); break;
case :
setEnd (-, -); break;
case :
setEnd (-, -); break;
case :
setEnd (-, -); break;
case :
setEnd (-, -); break;
case :
setEnd (-, -); break;
case :
setEnd (-, -); break;
case :
setEnd (-, -); break;
case :
setEnd (-, -); break;
case :
setEnd (-, -); break;
case :
setEnd (-, -); break;
case :
setEnd (-, -); break;
case :
setEnd (-, -); break;
case :
setEnd (-, -); break;
case :
setEnd (-, -); break;
case :
setEnd (-, -); break;
case :
setEnd (-, -); break;
case :
setEnd (-, -); break;
case :
setEnd (-, -); break;
case :
setEnd (-, -); break;
case :
setEnd (-, -); break;
case :
setEnd (-, -); break;
case :
setEnd (-, -); break;
case :
setEnd (-, -); break;
case :
setEnd (-, -); break;
case :
setEnd (-, -); break;
case :
setEnd (-, -); break;
case :
setEnd (-, -); break;
case :
setEnd (-, -); break;
case :
setEnd (-, -); break;
case :
setEnd (-, -); break;
case :
setEnd (-, -); break;
case :
setEnd (-, -); break;
case :
setEnd (-, -); break;
case :
setEnd (-, -); break;
case :
setEnd (-, -); break;
case :
setEnd (-, -); break;
default:
break;
}
} void MainWindow::setNextPos (int index)
{
switch (index) {
case :
setEnd(-, -); break;
case :
setEnd (-, -); break;
case :
setEnd (-, -); break;
case :
setEnd (-, -); break;
case :
setEnd (-, -); break;
case :
setEnd (-, -); break;
case :
setEnd (-, -); break;
case :
setEnd (-, -); break;
case :
setEnd (-, -); break;
case :
setEnd (-, -); break;
case :
setEnd (-, -); break;
case :
setEnd (-, -); break;
case :
setEnd (-, -); break;
case :
setEnd (-, -); break;
case :
setEnd (-, -); break;
case :
setEnd (-, -); break;
case :
setEnd (-, -); break;
case :
setEnd (-, -); break;
case :
setEnd (-, -); break;
case :
setEnd (-, -); break;
case :
setEnd (-, -); break;
case :
setEnd (-, -); break;
case :
setEnd (-, -); break;
case :
setEnd (-, -); break;
case :
setEnd (-, -); break;
case :
setEnd (-, -); break;
case :
setEnd (-, -); break;
case :
setEnd (-, -); break;
case :
setEnd (-, -); break;
case :
setEnd (-, -); break;
case :
setEnd (-, -); break;
case :
setEnd (-, -); break;
case :
setEnd (-, -); break;
case :
setEnd (-, -); break;
case :
setEnd (-, -); break;
case :
setEnd (-, -); break;
case :
setEnd (-, -); break;
case :
setEnd (-, -); break;
default:
break;
}
} void MainWindow::FindPath ()
{
//Demo 在图片上绘线 在原有基础上 (+700, +440);
QVector<QPoint> v; dj->dijkstra (startComboBox->currentIndex ());
//设置下一处的终点
nextPath = dj->get_Path (endComboBox->currentIndex ()); //准备绘制
Clear ();
//将路线绘制下来
QGraphicsPathItem *item = new QGraphicsPathItem(); QPen pen;
pen.setWidth ();
pen.setColor (Qt::red);
item->setPen (pen);
item->setFlag (QGraphicsItem::ItemIsPanel); // qDebug() << startX << " " << startY << " " << endX << " " << endY; // qDebug() << "Hello World !"; for (int i = ; i < nextPath.size (); i++) {
qDebug() << nextPath[i] << " , ";
}
scene->addItem (item); QPainterPath pa; //path pa.moveTo (startX + , startY + ); //将路径用坐标存入到路径
for (int i = ; i < nextPath.size() ; i++) {
setNextPos (nextPath[i]);
pa.lineTo (endX + , endY + );
}
item->setPath (pa); } void MainWindow::Clear ()
{
QList<QGraphicsItem*> listItem = scene->items ();
while (!listItem.empty ())
{
scene->removeItem (listItem.at ());
listItem.removeAt ();
}
QGraphicsPixmapItem *item =
scene->addPixmap (QPixmap("NanTong.jpg"));
// item->setFlag (QGraphicsItem::ItemIsMovable);
item->setPos (-, -);
} void MainWindow::Revise ()
{
QDialog *reviseDlg = new QDialog;
QLabel *reviseLabel = new QLabel(tr("修改图片路径:"));
QLineEdit *revison = new QLineEdit(tr("\\image\\library.png"));
QPushButton *SureBtn = new QPushButton(tr("确定"));
QPushButton *CancelBtn = new QPushButton(tr("取消")); revison->setEnabled (false); reviseComboBox = new QComboBox;
reviseComboBox->addItem (tr("图书馆"));
reviseComboBox->addItem (tr("食堂"));
reviseComboBox->addItem (tr("西操"));
reviseComboBox->addItem (tr("jsj教学楼")); connect(reviseComboBox, SIGNAL(activated(int)), this, SLOT(ShowDialog()));
connect (SureBtn, SIGNAL(clicked(bool)), reviseDlg, SLOT(close()));
connect (CancelBtn, SIGNAL(clicked(bool)), reviseDlg, SLOT(close ())); revison->setText (strPath); QGridLayout *mainlayout = new QGridLayout(reviseDlg);
mainlayout->addWidget (reviseLabel, , ); mainlayout->addWidget (revison, , );
mainlayout->addWidget (reviseComboBox, , );
mainlayout->addWidget (SureBtn, , , , ); mainlayout->addWidget (CancelBtn, , , , ); reviseDlg->setWindowTitle (tr("修改景点信息"));
reviseDlg->show ();
} void MainWindow::ShowDialog ()
{
strPath = QFileDialog::getOpenFileName (this, "打开", "/", "PNG图像(*.png)::JPEG图像(*.jpg)");
switch (reviseComboBox->currentIndex ()) {
case :
library.load (strPath); break;
case :
canteen.load (strPath); break;
case :
westground.load (strPath); break;
case :
jxjBuilding.load (strPath); break;
default:
break;
}
} //鼠标事件
void MainWindow::mouseDoubleClickEvent (QMouseEvent *e)
{
QDialog *dialog = new QDialog;
QGridLayout *layout = new QGridLayout(dialog);
label = new QLabel; qDebug() << "x : " << e->x () << ", y : " << e->y ();
//食堂(1060, 260)
if ( (e->x () >= - && e->x () <= + ) &&
(e->y () >= - && e->y () <= + ))
{
strPath = "images//canteen";
canteen.load (strPath);
label->setPixmap (canteen);
layout->addWidget (label);
dialog->setMinimumSize (, );
dialog->setWindowTitle ("二食堂");
dialog->show ();
}
else if ((e->x () >= - && e->x () <= + ) &&
(e->y () >= - && e->y () <= + ) ) {
strPath = "images//computer";
jxjBuilding.load (strPath);
label->setPixmap (jxjBuilding);
layout->addWidget (label);
dialog->setMinimumSize (, );
dialog->setWindowTitle ("计算机楼(方肇周教学楼)");
dialog->show ();
}
else if ((e->x () >= - && e->x () <= + ) &&
(e->y () >= - && e->y () <= + ) ) {
strPath = "images//library";
library.load (strPath);
label->setPixmap (library);
layout->addWidget (label);
dialog->setMinimumSize (, );
dialog->setWindowTitle ("图书馆");
dialog->show ();
}
else if ((e->x () >= - && e->x () <= + ) &&
(e->y () >= - && e->y () <= + ) ) {
strPath = "images//westgate";
westgate.load (strPath);
label->setPixmap (westgate);
layout->addWidget (label);
dialog->setMinimumSize (, );
dialog->setWindowTitle ("西大门");
dialog->show ();
}
else if ((e->x () >= - && e->x () <= + ) &&
(e->y () >= - && e->y () <= + ) ) {
strPath = "images//westground";
westground.load (strPath);
label->setPixmap (westground);
layout->addWidget (label);
dialog->setMinimumSize (, );
dialog->setWindowTitle ("西操");
dialog->show ();
}
else if ((e->x () >= - && e->x () <= + ) &&
(e->y () >= - && e->y () <= + ) ) {
strPath = "images//twoMarket";
twoMarket.load (strPath);
label->setPixmap (twoMarket);
layout->addWidget (label);
dialog->setMinimumSize (, );
dialog->setWindowTitle ("二超");
dialog->show ();
}
} void MainWindow::callOtherMap ()
{
mapWidget = new MapWidget;
mapWidget->show ();
}
#ifndef MAPWIDGET_H
#define MAPWIDGET_H #include <QGraphicsView>
#include <QLabel>
#include <QLineEdit>
#include <QPushButton>
#include <QMouseEvent> class MapWidget : public QGraphicsView
{
Q_OBJECT
public:
MapWidget();
void readMap(); //读取地图信息
QPointF mapToMap(QPointF); //用于实现场景坐标系与地图坐标间的映射.以获得某点的经纬度 public slots:
void slotZoom(int); //缩放信号
protected:
//完成地图的显示功能
void drawBackground (QPainter *painter, const QRectF &rect); void mouseMoveEvent (QMouseEvent *event);
private:
QPixmap map;
qreal zoom;
QLabel *viewCoord; //视图目前坐标(以窗口左上为原点)
QLabel *sceneCoord; //场景目前坐标(以场景中心为原点)
QLabel *mapCoord; //地图目前坐标 double x1, y1;
double x2, y2; }; #endif // MAPWIDGET_H
#include "mapwidget.h"
#include <QSlider> //滑动条
#include <QGridLayout>
#include <QFile>
#include <QTextStream>
#include <QGraphicsScene>
#include <math.h> MapWidget::MapWidget()
{
//读取地图信息--用于读取描述地图信息的文件(包括地图名及经纬度等信息)
readMap ();
zoom = ;
int width = map.width ();
int height = map.height ();
//新建一个QGraphicsScene对象为主窗口连接一个场景
QGraphicsScene *scene = new QGraphicsScene(this);
//限定场景的显示区域为地图大小
scene->setSceneRect (-width/, -height/, width, height);
setScene (scene);
/***
* The background is cached(隐藏,缓存). This affects both custom backgrounds, and
* backgrounds based on the backgroundBrush property. When this flag is enabled,
* QGraphicsView will allocate one pixmap with the full size of the viewport
*/
setCacheMode (CacheBackground);
/***
* 用于地图缩放的滑动条
* 新建一个QSlider对象作为地图的缩放控制
*/
QSlider *slider = new QSlider;
//设置滚动条方向-垂直
slider->setOrientation (Qt::Vertical);
slider->setRange (, ); //设置地图缩放比例值范围为0~100
slider->setTickInterval (); //显示刻度间隔为10
slider->setValue (); //设置当前初始值为50
// 将缩放控制条的valueChanged()信号与地图缩放slotZoom()槽函数相关联
connect (slider, SIGNAL(valueChanged(int)), this, SLOT(slotZoom(int))); //缩放图标
QLabel *zoominLabel = new QLabel;
zoominLabel->setScaledContents (true);
zoominLabel->setPixmap (QPixmap("zoomin.png"));
QLabel *zoomoutLabel = new QLabel;
zoomoutLabel->setScaledContents (true);
zoomoutLabel->setPixmap (QPixmap("zoomout.png")); //坐标值显示区
QLabel *label1 = new QLabel(tr("GraphicsView:"));
viewCoord = new QLabel;
QLabel *label2 = new QLabel(tr("GraphicsScene:"));
sceneCoord = new QLabel;
QLabel *label3 = new QLabel(tr("map:"));
mapCoord = new QLabel; //坐标显示区布局
QGridLayout *gridLayout = new QGridLayout;
gridLayout->addWidget (label1, , );
gridLayout->addWidget (viewCoord, , ); gridLayout->addWidget (label2, , );
gridLayout->addWidget (sceneCoord, , ); gridLayout->addWidget (label3, , );
gridLayout->addWidget (mapCoord, , ); gridLayout->setSizeConstraint (QLayout::SetFixedSize);
QFrame *coordFrame = new QFrame;
coordFrame->setLayout (gridLayout); //缩放控制子布局
QVBoxLayout *zoomLayout = new QVBoxLayout;
zoomLayout->addWidget (zoominLabel);
zoomLayout->addWidget (slider);
zoomLayout->addWidget (zoomoutLabel); //坐标显示区布局
QVBoxLayout *coordLayout = new QVBoxLayout;
coordLayout->addWidget (coordFrame);
coordLayout->addStretch ();
//主布局
QHBoxLayout *mainLayout = new QHBoxLayout;
mainLayout->addLayout (zoomLayout);
mainLayout->addLayout (coordLayout);
mainLayout->addStretch (); //平均分割
mainLayout->setMargin (); //设置对话框(或窗体)的边距为30
mainLayout->setSpacing (); //设定各个控件之间的间距为10
setLayout (mainLayout); //在场景中设置为布局 setWindowTitle ("Map Widget");
setMinimumSize (, );
} //读取地图信息
void MapWidget::readMap ()
{
QString mapName;
//新建一个QFile对象,“map.txt"是描述地图信息的文本文件
QFile mapFile("maps.txt");
//以"只读"的方式打开此文件
int ok = mapFile.open (QIODevice::ReadOnly);
if (ok) //分别以读取地图的名称和四个经纬度信息
{
QTextStream ts(&mapFile);
if (!ts.atEnd ()) { //没有到末尾返回false
ts >> mapName; //储存字符串
ts >> x1 >> y1 >> x2 >> y2; //储存地图左上角和右下角的经纬度
}
}
map.load (mapName); //将地图读取至私有标量map中
} //根据缩放滑动条的当前值,确定缩放的比例,调用scale()函数实现地图缩放--完成地图缩放功能slotZoom
void MapWidget::slotZoom (int value)
{
qreal s; //缩放大小
if (value > zoom) { //放大
s = pow (1.01, (value - zoom));
}
else {
s = pow(/1.01, (zoom - value));
}
scale(s, s);
zoom = value; //当前放大值
} //drawBackground()--以地图图片重绘场景的背景来实现地图显示
void MapWidget::drawBackground (QPainter *painter, const QRectF &rect)
{
/***
* The scene rectangle defines the extent of the scene, and in the view's case,
* this means the area of the scene that you can navigate using the scroll bars.
*/
painter->drawPixmap (int(sceneRect ().left ()) + , int(sceneRect ().top ()) - , map); } //完成某点在各层坐标中的映射及显示
void MapWidget::mouseMoveEvent (QMouseEvent *event)
{
//QGraphicesView 坐标
QPoint viewPoint = event->pos (); //鼠标事件位置
viewCoord->setText (QString::number (viewPoint.x ()) + "," + QString::number (viewPoint.y ())); //QGraphiccsScene 坐标 -- 将视图坐标转换成场景坐标
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 ())); } //完成从场景至地图坐标的转换mapToMap()
QPointF MapWidget::mapToMap (QPointF p)
{
QPointF latLon; //地图坐标
qreal w = sceneRect ().width (); //场景长度
qreal h = sceneRect ().height (); //场景高度
qreal lon = y1 - ( (h/+p.y ()) * abs(y1-y2)/h );
qreal lat = x1 + ( (w/+p.x ()) * abs(x1-x2)/w ); latLon.setX (lat);
latLon.setY (lon);
return latLon;
}
#include "mainwindow.h"
#include "mapwidget.h"
#include <QApplication>
#include <QFont>
#include <QDebug>
#include <QPixmap>
#include <QSplashScreen> int main(int argc, char *argv[])
{
QApplication a(argc, argv);
QPixmap pixmap(""); //创建QPixmap对象,设置启动图片
QSplashScreen splash(pixmap); //利用QPixmap对象创建一个QSplashScreen对象
splash.show (); //显示此启动图片 a.processEvents (); //使程序在显示启动动画的同时能能响应鼠标等其他事件 QFont font("ARPL KaitiM GB", );
font.setBold (true);
a.setFont (font); qDebug() << "Run............";
MainWindow w;
w.show (); //表示在主窗体对象初始化完成后,结束启动画面
splash.finish (&w); return a.exec();
}
源码下载: http://pan.baidu.com/s/1boEzMJt
qt新手,如有错误,希望大神们指正~
QT_地图导航 源码下载的更多相关文章
- openlayers4 入门开发系列之地图导航控件篇(附源码下载)
前言 openlayers4 官网的 api 文档介绍地址 openlayers4 api,里面详细的介绍 openlayers4 各个类的介绍,还有就是在线例子:openlayers4 官网在线例子 ...
- 百度地图 api 功能封装类 (ZMap.js) 本地搜索,范围查找实例 [源码下载]
相关说明 1. 界面查看: 吐槽贴:百度地图 api 封装 的实用功能 [源码下载] 2. 功能说明: 百度地图整合功能分享修正版[ZMap.js] 实例源码! ZMap.js 本类方法功能大多使用 ...
- 百度地图 api 功能封装类 (ZMap.js) 新增管理事件功能 [源码下载]
ZMap 功能说明 ZMap.js 本类方法功能大多使用 prototype 原型 实现: 包含的功能有:轨迹回放,圈画区域可编辑,判断几个坐标是否在一个圆圈内,生活服务查询,从经纬度获取地址信息,地 ...
- QT_文本编辑器_源码下载
源码下载: 链接: http://pan.baidu.com/s/1c21EVRy 密码: qub8 实现主要的功能有:新建,打开,保存,另存为,查找(查找的时候需要先将光标放到最下面位置才能查全,不 ...
- Android仿今日头条和知乎等App顶部滑动导航实现代码分析及源码下载
一.本文所涉及到的知识点 源码下载 二.目标 通过利用ViewPager+FragmentStatePagerAdapter+TabLayout 实现顶部滑动效果,如图: 三.知识点讲解 1.View ...
- web前端的十种jquery特效及源码下载
1.纯CSS3实现自定义Tooltip边框 涂鸦风格 这是一款用纯CSS3打造的自定义Tooltip边框的应用,之前我们讨论过如何用CSS3来实现不同样式的Tooltip,今天的这款Tooltip却可 ...
- C# ini文件操作【源码下载】
介绍C#如何对ini文件进行读写操作,C#可以通过调用[kernel32.dll]文件中的 WritePrivateProfileString()和GetPrivateProfileString()函 ...
- C# Excel导入、导出【源码下载】
本篇主要介绍C#的Excel导入.导出. 目录 1. 介绍:描述第三方类库NPOI以及Excel结构 2. Excel导入:介绍C#如何调用NPOI进行Excel导入,包含:流程图.NOPI以及C#代 ...
- C# 条形码操作【源码下载】
本篇介绍通过C#生成和读取一维码.二维码的操作. 目录 1. 介绍:介绍条形码.条形码的分类以及ZXing.Net类库. 2. 一维码操作:包含对一维码的生成.读取操作. 3. 二维码操作:包含对二维 ...
随机推荐
- Mesos的用途
http://mesos.apache.org/ https://mesosphere.com/why-mesos/ http://www.cnblogs.com/ee900222/p/docker_ ...
- NAT模式下VMware中CentOS7无法连接外网的解决方法
故障现象 ----------------------------------------------------------------------------------------------- ...
- 热修改 MySQL 数据库 pt-online-schema-change 的使用详解
由于周五公司团建的关系所以此篇推迟了抱歉. 首先不得不在该篇里面梳理一个数据库热增加删除字段表的工具 pt-online-schema-change 这个工具在前面我的博文 <关于utf8mb4 ...
- 一本通1587【例 3】Windy 数
1587: [例 3]Windy 数 时间限制: 1000 ms 内存限制: 524288 KB 题目描述 原题来自:SCOI 2009 Windy 定义了一种 Windy 数:不含前 ...
- pgm16
前面结束了关于 learning 部分一些粗浅的讨论,我们大概明白了一些 learning 中 common sense/techniques.剩下的部分我们分为 causality 和 utilit ...
- fio 磁盘性能
/fio -ioengine=libaio -bs=32k -direct=1 -thread -rw=randrw -percentage_random=100,0 -size=10G -filen ...
- BZOJ5415[Noi2018]归程——kruskal重构树+倍增+堆优化dijkstra
题目描述 本题的故事发生在魔力之都,在这里我们将为你介绍一些必要的设定. 魔力之都可以抽象成一个 n 个节点.m 条边的无向连通图(节点的编号从 1 至 n).我们依次用 l,a 描述一条边的长度.海 ...
- xml和对象 转换
//测试数据 static List<User> list = new List<User>() { new User(){id=1001 ,name="语文&quo ...
- Linux 下统计Apache每分钟的并发数
脚本非常简单,不清楚原理,逐行运行即可. 使用时将脚本复制到home目录,并添加执行权限.定时任务即可. 代码内容如下: #!/bin/sh date >> /home/date-time ...
- 洛谷 P10P1343 地震逃生 改错
P1343 地震逃生 题目描述 汶川地震发生时,四川**中学正在上课,一看地震发生,老师们立刻带领x名学生逃跑,整个学校可以抽象地看成一个有向图,图中有\(n\)个点,\(m\)条边.1号点为教室,\ ...