一、前言

在线地图模块在一开始设计整个系统的时候就考虑进去了,主要功能就是在摄像机管理中,提供经纬度信息,然后加载百度地图在浏览器中显示,根据摄像机信息表中的每个摄像机的经纬度信息,自动生成设备点在地图中,地图是在线的,支持鼠标拖动、滚动缩放等,设备的信息通过一开始写入到html文件中加载的,也可以做成js交互,Qt封装了浏览器控件,在Qt5.6以前是webkit,5.6以后改成了webengine,其实就是谷歌内核的浏览器,由于谷歌内核浏览器不再支持mingw编译器,只提供了msvc版本,所以意味着在windows上的mingw版本的Qt5.6以上版本,已经再无Qt带的浏览器控件可用,只能使用ie,采用qaxwidget的形式加载,所以建议如果一定要使用浏览器控件的话,Qt5.6以上的版本最好选用msvc编译器,相信在windows上做开发的人员,大部分都会安装宇宙无敌的VS开发环境的,所以在安装Qt集成开发环境的时候勾选msvc版本的Qt即可。

很多年前就封装过这个百度地图的类,主要有三个功能,第一个是传入设备的名称、经纬度信息集合,自动加载设备分布图;第二个是按照设定的查询路线规则查询对应的最优路线;第三个是提供js交互功能,鼠标按下处获取对应经纬度。其中围绕这三个功能做了很多可控的参数设置,比如是否启用鼠标滚轮缩放、是否显示缩略图、比例尺、全景、路况信息等。大概从2019年6月份开始百度地图对绝大部分功能都开始收费了,只提供了基础的功能免费比如设备分布图,连样式功能也要收费了,哎!

通用视频控件开源:https://gitee.com/feiyangqingyun/QWidgetDemo https://github.com/feiyangqingyun/QWidgetDemo

文件名称:videowidget

体验地址:https://gitee.com/feiyangqingyun/QWidgetExe https://github.com/feiyangqingyun/QWidgetExe

文件名称:bin_video_system.zip

二、功能特点

  1. 支持16画面切换,全屏切换等,包括1+4+6+8+9+13+16画面切换。
  2. 支持alt+enter全屏,esc退出全屏。
  3. 自定义信息框+错误框+询问框+右下角提示框。
  4. 17套皮肤样式随意更换,所有样式全部统一,包括菜单等。
  5. 云台仪表盘鼠标移上去高亮,八个方位精准识别。
  6. 底部画面工具栏(画面分割切换+截图声音等设置)移上去高亮。
  7. 可在配置文件更改左上角logo+中文软件名称+英文软件名称。
  8. 封装了百度地图,三维切换,设备点位,鼠标按下获取经纬度等。
  9. 堆栈窗体,每个窗体都是个单独的qwidget,方便编写自己的代码。
  10. 顶部鼠标右键菜单,可动态控制时间CPU+左上角面板+左下角面板+右上角面板+右下角面板的显示和隐藏,支持恢复默认布局。
  11. 工具栏可以放置多个小图标和关闭图标。
  12. 左侧右侧可拖动拉伸,并自动记忆宽高位置,重启后恢复。
  13. 双击摄像机节点自动播放视频,双击节点自动依次添加视频,会自动跳到下一个,双击父节点自动添加该节点下的所有视频。
  14. 摄像机节点拖曳到对应窗体播放视频,同时支持拖曳本地文件直接播放。
  15. 视频画面窗体支持拖曳交换,瞬间响应。
  16. 双击节点+拖曳节点+拖曳窗体交换位置,均自动更新url.txt。
  17. 支持从url.txt中加载16通道视频播放,自动记忆最后通道对应的视频,软件启动后自动打开播放。
  18. 右下角音量条控件,失去焦点自动隐藏,音量条带静音图标。
  19. 集成百度地图,可以添加设备对应位置,自动生成地图,支持缩放和三维地图,提供地图风格选择,共12种风格。
  20. 视频拖动到通道窗体外自动删除视频。
  21. 鼠标右键可删除当前+所有视频,截图当前+所有视频。
  22. 录像机管理、摄像机管理,可添加删除修改导入导出打印信息,立即应用新的设备信息生成树状列表,不需重启。
  23. 在pro文件中可以自由开启是否加载地图。
  24. 视频播放可选四种内核自由切换,vlc+ffmpeg+easyplayer+海康sdk,均可在pro中设置。
  25. 可设置1+4+9+16画面轮询,可设置轮询间隔以及轮询码流类型等,直接在主界面底部工具栏右侧单击启动轮询按钮即可,再次单击停止轮询。
  26. 默认超过10秒钟未操作自动隐藏鼠标指针。
  27. 支持onvif搜素设备,支持任意onvif摄像机,包括但不限于海康大华宇视天地伟业华为等,支持onvif云台控制。
  28. 高度可定制化,用户可以很方便的在此基础上衍生自己的功能,支持linux系统。

三、效果图

四、核心代码

#include "frmmapweb.h"
#include "ui_frmmapweb.h"
#include "quiwidget.h"
#include "iconfont.h"
#include "mapbaidu.h" MapData *MapData::Instance()
{
static MapData self;
return &self;
} void MapData::submit(const QString &point)
{
emit receivePoint(point);
} frmMapWeb::frmMapWeb(QWidget *parent) : QWidget(parent), ui(new Ui::frmMapWeb)
{
ui->setupUi(this);
this->initForm();
this->initTree();
this->initMap();
this->loadMap();
} frmMapWeb::~frmMapWeb()
{
delete ui;
} void frmMapWeb::initForm()
{
connect(AppEvent::Instance(), SIGNAL(saveIpcInfo()), this, SLOT(loadMap()));
ui->widgetRight->setFixedWidth(App::RightWidth); ui->navTitle1->setText("信息设置");
ui->navTitle2->setText("图层管理");
ui->navTitle1->setLeftIcon(0xf041);
ui->navTitle2->setLeftIcon(0xf1b2);
ui->navTitle2->setRightIcon5(0xf1f8);
} void frmMapWeb::initTree()
{
ui->treeWidget->clear();
ui->treeWidget->setAnimated(false);
ui->treeWidget->setHeaderHidden(true);
//ui->treeWidget->setIndentation(0); QStringList texts;
texts << "A" << "B" << "C" << "D"; for (int i = 0; i < texts.count(); i++) {
//添加父节点
QTreeWidgetItem *itemParent = new QTreeWidgetItem(ui->treeWidget);
itemParent->setText(0, QString("图层%1").arg(texts.at(i))); //循环添加子节点
for (int j = 0; j < 5; j++) {
QTreeWidgetItem *itemChild = new QTreeWidgetItem(itemParent);
itemChild->setText(0, QString("%1%2").arg((j % 2 == 0) ? "地形" : "山脉").arg(j + 1));
QPixmap iconNormal = IconFont::Instance()->getPixmap(QUIConfig::TextColor, (j % 2 == 0) ? 0xe6f2 : 0xe6ed, 18, 20, 20);
itemChild->setIcon(0, iconNormal);
}
} ui->treeWidget->expandAll();
} void frmMapWeb::initMap()
{
#ifdef webkit
QWebSettings *webSetting = QWebSettings::globalSettings();
webSetting->setAttribute(QWebSettings::JavascriptEnabled, true);
webSetting->setAttribute(QWebSettings::PluginsEnabled, true);
webSetting->setAttribute(QWebSettings::JavascriptCanOpenWindows, true); webView = new QWebView;
ui->layout->addWidget(webView);
connect(webView->page(), SIGNAL(loadFinished(bool)), this, SLOT(loadFinished()));
#elif webengine
QWebEngineSettings *webSetting = QWebEngineSettings::globalSettings();
webSetting->setAttribute(QWebEngineSettings::JavascriptEnabled, true);
webSetting->setAttribute(QWebEngineSettings::PluginsEnabled, true);
webSetting->setAttribute(QWebEngineSettings::JavascriptCanOpenWindows, true); webView = new QWebEngineView;
ui->layout->addWidget(webView); QWebChannel *channel = new QWebChannel(this);
channel->registerObject("objName", MapData::Instance());
webView->page()->setWebChannel(channel);
connect(MapData::Instance(), SIGNAL(receivePoint(QString)), this, SLOT(submit(QString)));
connect(webView->page(), SIGNAL(loadFinished(bool)), this, SLOT(loadFinished()));
#elif webie
webView = new QAxWidget;
ui->layout->addWidget(webView);
webView->setControl("{8856F961-340A-11D0-A96B-00C04FD705A2}");
#endif
} void frmMapWeb::loadMap()
{
QString fileName = QUIHelper::appPath() + "/config/deviceall.html";
MapBaiDu::Instance()->reset();
MapBaiDu::Instance()->setEnableClickPoint(true);
MapBaiDu::Instance()->setMapGeocoder("上海市");
#ifndef webie
MapBaiDu::Instance()->setCallFun(QString("%1.submit").arg("objName"));
#endif QStringList deviceNames, deviceAddrs, devicePoints;
#if 0
for (int i = 1; i <= 100; i++) {
deviceNames << QString("摄像头%1").arg(i);
deviceAddrs << QString("测试地址%1").arg(i);
devicePoints << QString("121.%1,31.%2").arg(qrand() % 1000000).arg(qrand() % 1000000);
}
#elif 0
deviceNames << "摄像头1" << "摄像头2" << "摄像头3" << "摄像头4" << "摄像头5";
deviceAddrs << "安波路533弄1号楼" << "北新路8号" << "康桥镇康桥路1200号(御青路)" << "闵行区诸翟镇纪翟南路" << "浦东新区广兰路1080号(紫薇路口)";
devicePoints << "121.534942,31.307706" << "121.572075,31.188825" << "121.57987,31.155795" << "121.292628,31.215278" << "121.626992,31.211056";
#else
//从数据库加载
deviceNames = DBData::IpcInfo_IpcName;
deviceAddrs = DBData::IpcInfo_IpcAddr;
devicePoints = DBData::IpcInfo_IpcPosition;
#endif MapBaiDu::Instance()->setShowTrafficControl(true);
//MapBaiDu::Instance()->setShowMapTypeControl(true);
MapBaiDu::Instance()->setShowNavigationControl(true);
MapBaiDu::Instance()->setMarkerInfo(deviceNames, deviceAddrs, devicePoints);
MapBaiDu::Instance()->saveMap(fileName); QString url = "file:///" + fileName;
#ifdef webkit
webView->load(QUrl(url));
#elif webengine
webView->load(QUrl(url));
#elif webie
webView->dynamicCall("Navigate(const QString&)", url);
#endif
} void frmMapWeb::submit(const QString &point)
{
//演示如何从地图上标注点获取到经纬度
if (!point.isEmpty()) {
QStringList list = point.split(",");
double longitude = list.at(0).toDouble();
double latitude = list.at(1).toDouble(); //取小数点后6位
QString strLongitude = QString::number(longitude, 'f', 6);
QString strLatitude = QString::number(latitude, 'f', 6);
ui->txtLongitude->setText(strLongitude);
ui->txtLatitude->setText(strLatitude);
}
} void frmMapWeb::loadFinished()
{
#ifdef webkit
webView->page()->mainFrame()->addToJavaScriptWindowObject("objName", this);
#endif
}

Qt编写安防视频监控系统17-在线地图的更多相关文章

  1. Qt编写安防视频监控系统(界面很漂亮)

    一.前言 视频监控系统在整个安防领域,已经做到了烂大街的程序,全国起码几百家公司做过类似的系统,当然这一方面的需求量也是非常旺盛的,各种定制化的需求越来越多,尤其是这几年借着人脸识别的东风,发展更加迅 ...

  2. Qt编写安防视频监控系统18-云台控制

    一.前言 云台控制是视频监控系统中必备的一个功能,对球机进行上下左右的移动,还有焦距的控制,其实核心就是控制XYZ三个坐标轴,为了开发这个模块,特意研究了各种云台控制的方法和开源库比如soap,有些厂 ...

  3. Qt编写安防视频监控系统12-异形布局

    一.前言 视频监控系统中,除了常规的1画面.4画面.9画面.16画面以外,还有几个布局比较另类,比如6画面.8画面.13画面,有些通道需要占据不同的行列,4画面.9画面.16画面都是非常对称的布局,行 ...

  4. Qt编写安防视频监控系统11-动态换肤

    一.前言 Qt中的动态换肤技术是非常一流的,直接调用qApp->setStyleSheet(qss);就可以对整个应用程序进行换肤,如果样式表内容不多,或者对应的贴图不对,效率还是蛮好的,不过据 ...

  5. Qt编写安防视频监控系统9-自动隐藏光标

    一.前言 这个效果的灵感来自于大屏电子看板系统,在很多系统中尤其是上了大屏的时候,其实在用户不在操作的时候,是很不希望看到那个鼠标箭头指针的,只有当用户操作的时候才显示出来,这个就需要开个定时器定时计 ...

  6. Qt编写安防视频监控系统8-双击节点

    一.前言 在所有的视频监控系统中,双击摄像机的节点,对应摄像机加载到当前焦点通道显示,这个都是必须具备的功能,还有一些厂家会做双击NVR节点,自动加载该NVR下的所有摄像机全部显示,从通道1开始到通道 ...

  7. Qt编写安防视频监控系统7-全屏切换

    一.前言 全屏切换这个功能点属于简单的,一般会做到右键菜单中,也提供了快捷键比如alt+enter来触发,恢复全屏则按esc即可,全屏处理基本上都是隐藏通道面板以外的窗体,保持最大化展示,由于采用了模 ...

  8. Qt编写安防视频监控系统5-视频回放

    一.前言 一般视频回放都会采用GB28181国标来处理,这样可以保证兼容国内各大厂家的NVR,毕竟在同一的国家标准下,大家都会统一支持国标的,就不需要根据各个厂家的SDK来做兼容处理,烦得很,厂家越来 ...

  9. Qt编写安防视频监控系统3-通道交换

    一.前言 最开始写通道交换的功能的时候,走了很多弯路,比如最开始用最初级的办法,触发交换的时候,先关闭视频,然后设置新的url重新打开视频,这样处理非常低级而且耗内存还卡还很慢,毕竟重新打开视频都需要 ...

随机推荐

  1. qt5.12 解决显示中文乱码问题

    在菜单栏   文件->选项,找到文本编辑器 文件编码设置如图 在cpp文件中加入 #pragma execution_character_set("utf-8") 之后就可以 ...

  2. 随笔记录--Array类型

    前言:除了Object类型之外,Array类型恐怕是ECMAScript中最常用的类型了.而且,ECMAScript中数组与其他多数语言中的数组有很大差别,ECMAScript数组中的每一项可以保存任 ...

  3. Vuex之store仓库计算属性Getter

    (1)简介 Getter相当于vue中的computed计算属性,getter 的返回值会根据它的依赖被缓存起来,且只有当它的依赖值发生了改变才会被重新计算,这里可以通过定义vuex的Getter来获 ...

  4. 第9章 MyBatis的关系映射

    在实际开发中,对数据库的操作通常涉及多张表,涉及了对象和对象之间的关联关系.针对多表之间的操作,MyBatis提供了关联映射,通过关联映射就可以很好的处理对象与对象之间的关联关系 9.1 关联关系概述 ...

  5. es6 -- 与解构赋值默认值结合使用

    参数默认值可以与解构赋值的默认值,结合起来使用. function foo({x, y = 5}) { console.log(x, y) } foo({}) // undefined 5 foo({ ...

  6. [Algorithm] 136. Single Number

    Given a non-empty array of integers, every element appears twice except for one. Find that single on ...

  7. eslint Cannot read property 'range' of null错误

    eslint Cannot read property 'range' of null错误   手动添加的配置,2个项目OK,还个项目 运行报错 Cannot read property 'range ...

  8. CLR调试时的sos.dll/clr.dll/mscorwks.dll/mscordacwks.dll等动态库的版本对应

    大家都知道,在调试托管代码时,一定会加载到sos/clr/mscorwks/mscordacwks这些动态库,才能够很好的完成我们的调试工作,那么他们的版本对应关系是怎样的呢,特别是clr.dll/m ...

  9. 了解Vuex状态管理模式的理解强化指南

    1 Vuex是什么呢?它是Vue的状态管理模式,在使用vue的时候,需要在vue中各个组件之间传递值是很痛苦的,在vue中我们可以使用vuex来保存我们需要管理的状态值,值一旦被改变,所有引用该值的地 ...

  10. kernel 获取ntoskrnl.exe基址

    标题: kernel shellcode之寻找ntoskrnl.exe基址 http://scz.617.cn:8/windows/201704171416.txt 以64-bits为例,这是Eter ...