Qml是js的扩展版,继承至Google JS NoteV8(有兴趣的可以去看JS的开源)
qt把metaObject在js中插入才有了qml,当然,自己派生的类需要自己动态注册的,qml才可以调用(有兴趣的可以去看qml这部分的源码)。加载qml过程你可以看做是自动组织成一个程序,不过是都是已经实现的。
qml大部分需要自己实现一些c++代码来管理数据或实现一些业务逻辑,不然就是个空架子;有时候甚至要做一些c++界面绘制。这样就要求组织代码,不然程序会很混乱。举个例子,做过飞控的可能知道PX4的开源项目,有个QGroundControl地面站项目,那就是代码组织混乱的代名词,c++类在qml中到处有实例,我也做过地面站,本来想使用QGC,后来发现根本改不懂,只好完全重写了,其中可用的只有地图和mavlink连接(实际上飞控连接大多使用4G,蓝牙基本没有什么用),改改bug,配置协议就可以了,当然也不能怪别人,毕竟只是个实验室框架
贴一段地图使用及插入其它元素,限与是商业用途不能开源,只贴头文件
import QtQuick 2.2
import QtLocation 5.5
import QtPositioning 5.5
import QtQuick.Controls 1.4
import QtQuick.Controls.Styles 1.4
import VGGroundControl 1.0
/*
* 封装的地图页面:地图显示页面,包括地图的放大、缩小,位置,地块轮廓组件显示等;
*
*/
Map {
id: root
center: mapManager.mapCenter
zoomLevel: mapManager.zoomLevel
plugin: Plugin {name: "VGMapControl"}
gesture.flickDeceleration: 3000
gesture.enabled: true
gesture.acceptedGestures: MapGestureArea.PanGesture | MapGestureArea.FlickGesture | MapGestureArea.PinchGesture
property alias bDrawCenter: imgCenter.visible
property alias bShowBluetoooth: rctBlT.visible
property int managerObj: VGMapManager.Land
property bool bShowScale: true
property double latDBC: 0
property double lonDBC: 0
property point pntDBC: Qt.point(0,0)
property bool bDBC: false
property bool bEnableEdit: false
property real fScaleBottom: 0
property real fBtnTop: 0
signal cilickedCoordinate(VGCoordinate coor)
signal dbCilickedCoordinate(VGCoordinate coor)
signal clickBtn(string txt)
signal shrinkEdgeSelected()
function updateMap() {
var mapTypeName = mapManager.propertyMapName(managerObj===0)
for (var i = 0; i < root.supportedMapTypes.length; i++) {
if(mapTypeName === root.supportedMapTypes[i].name)
{
root.activeMapType = root.supportedMapTypes[i]
calculateScale()
break
}
}
}
//设置地图中心图标
function setCurPosition(coor) {
markerCenter.visible = true
markerCenter.coordinate = coor
}
function addBtn(txt, imgNomal, imgPress) {
var vis = imgNomal.length>0
btnModel.append({"btnText":txt, "imgNomal":imgNomal, "imgPress":imgPress, "btnVisible":vis})
}
function addOptionBtn(txt, imgNomal, imgPress) {
btnOption.addBtn(txt, imgNomal, imgPress)
}
function clearOptionBtn() {
btnOption.clearBtn()
}
function setBtnVisible(txt, vis) {
for (var i = 0; i < btnModel.count; ++i){
if (txt === btnModel.get(i).btnText){
btnModel.setProperty(i, "btnVisible", vis)
break
}
}
}
ListModel{
id: btnModel
function hasBtn(txt){
for (var i = 0; i< count; ++i){
if (txt === get(i).btnText)
return true
}
return false
}
}
//计算比例尺
function calculateScale() {
if (!bShowScale)
return
scaleText.text = mapManager.calculatePixLength(toCoordinate(Qt.point(0,0)), toCoordinate(Qt.point(0,80)), 80)
}
Component.onCompleted: {
updateMap()
}
Timer {
id: scaleTimer
interval: 100
running: false
repeat: false
onTriggered: calculateScale()
}
onZoomLevelChanged: {
calculateScale()
if(root.zoomLevel !== mapManager.zoomLevel)
mapManager.zoomLevel = root.zoomLevel
if (bDBC) {
var newCoor = root.toCoordinate(pntDBC,false)
bDBC = false
var azimuth = newCoor.azimuthTo(root.center)
var distance = newCoor.distanceTo(root.center)
root.center = QtPositioning.coordinate(latDBC, lonDBC).atDistanceAndAzimuth(distance, azimuth)
}
}
onWidthChanged: scaleTimer.restart()
onHeightChanged: scaleTimer.restart()
onCenterChanged: mapManager.mapCenter = center
//当前位置图标
MapQuickItem {
id: markerCenter
anchorPoint.x: markPointImg.width/2
anchorPoint.y: markPointImg.height/2
coordinate : landManager.curCoordinate
visible: landManager.curCoordinate.isValid
z: 120
sourceItem: Image {
id: markPointImg
enabled: landManager.curCoordValid
source: enabled ? "qrc:/images/marker.png" : "qrc:/images/marker_grey.png"
sourceSize.width: 30
sourceSize.height: 30
}
}
//飞机
MapItemView {
model: mapManager.getSpecItems(MapAbstractItem.Type_PlantInfo)
delegate: MapQuickItem{
anchorPoint.x: plantImg.width/2
anchorPoint.y: plantImg.height/2
coordinate : object.coordinate
visible: object.monitor && (managerO