我正在使用 QML 和 Qt 5.11 開發開放街道地圖功能。我剛剛寫了一個最小的重現案例。它包括在地圖上顯示一個藍點。當我用滑鼠滾輪更改地圖縮放時,會計算比例因子,當這個比例大于 0.1 時,應該顯示藍點,否則不顯示。
在我的地圖組件中,我創建了一個 scale 屬性,它是 scaleFactor() 函式的別名。在我的地圖中,我使用包含MapQuickItem作為委托的 MapItemView ,并且此 MapQuickItem 包含一個包含Canvas的Rectangle。
我的第一個想法是在我的 Rectangle 中添加一個屬性別名來獲取 onScaleChanged 事件,如下所示:
property alias scale: map.scale
onScaleChanged: {
myCanvas.requestPaint();
}
但這不起作用,因為 qmlscene 工具中的錯誤訊息是:
第 51 行 無效的別名參考。找不到 ID“地圖”。
我很確定問題是因為我在 MapItemView 中,但我找不到任何相關資訊。
因此,非常感謝任何幫助。
myfile.qml 上的內容
import QtQuick 2.11
import QtQuick.Controls 2.4
import QtLocation 5.11
import QtPositioning 5.11
import QtQuick.Window 2.11
Window {
id: root; width: 800; height: 600;
Plugin { id: mapPlugin; name: "osm"; }
ListModel {
id: myModel
ListElement { latitude: 48.2351164; longitude: 6.8986936; }
}
Map {
id: map
anchors.fill: parent
plugin: mapPlugin
center: QtPositioning.coordinate(48.2351164, 6.8986936)
zoomLevel: 19
property real scale: map.scaleFactor()
onScaleChanged: {
console.log(">>> scale from map component", scale);
}
// function reimplemented from qdeclarativegeomapquickitem.cpp
function scaleFactor() {
return Math.pow(0.5, map.maximumZoomLevel - map.zoomLevel);
}
MapItemView {
model: myModel
delegate: MapQuickItem {
anchorPoint.x: myRect.width / 2
anchorPoint.y: myRect.height / 2
width: myRect.width
height: myRect.height
zoomLevel: map.maximumZoomLevel // set the zoomLevel (1:1 scale)
coordinate: QtPositioning.coordinate(model.latitude, model.longitude)
sourceItem: Rectangle {
id: myRect
readonly property int radius: 50
property alias scale: map.scale
onScaleChanged: {
myCanvas.requestPaint();
}
width: radius * 2
height: radius * 2
color: "transparent"
Canvas {
id: myCanvas
anchors.fill: parent
onPaint: {
var width = myRect.width;
var height = myRect.height;
var centreX = width / 2;
var centreY = height / 2;
var ctx = getContext("2d");
ctx.reset();
if (scale > 0.1) {
ctx.fillStyle = "blue";
ctx.globalAlpha = 1;
ctx.beginPath();
ctx.moveTo(centreX, centreY);
ctx.arc(centreX, centreY, myRect.radius, 0, Math.PI * 2, false);
ctx.closePath();
ctx.fill();
}
}
}
}
}
}
}
}
只需運行 qmlscene myfile.qml 即可執行。
uj5u.com熱心網友回復:
下面的作業代碼。
問題在于,雖然 MapQuickItem 似乎位于 myfile.qml 組件的命名空間中,但實際上并非如此。委托實際上是組件本身并開始一個新的命名空間。您可以認為委托最終出現在一個新的匿名組件中,該組件無法參考它所在的周圍組件中的 id。
但是,雖然它不能參考周圍組件中的 id,但它可以參考組件視覺層次結構中的組件 id。因此,您可以在運行時構建此可視層次結構時實體化的組件層次結構中參考根(此檔案組件本身的 id)。
從那里,您可以在根物件上宣傳此組件私有的 Map 組件作為別名,然后通過 MapItemView 中的根參考參考它。
起初這有點令人困惑,但當您開始意識到組件是由檔案、組件或委托定義的 QML 集群時,這才有意義。組件內的 id 參考很好,但外部參考必須作為屬性向下傳遞,或者在委托情況下通過向上的組件層次結構參考。然后必須將組件的子 QML 物件宣傳為別名以提供外部訪問權限。
更多資訊在這里:
https://doc.qt.io/qt-5/qtqml-documents-scope.html
import QtQuick 2.11
import QtQuick.Controls 2.4
import QtLocation 5.11
import QtPositioning 5.11
import QtQuick.Window 2.11
Window {
id: root; width: 800; height: 600;
visible: true
property alias map: map
Plugin { id: mapPlugin; name: "osm"; }
ListModel {
id: myModel
ListElement { latitude: 48.2351164; longitude: 6.8986936; }
}
Map {
id: map
anchors.fill: parent
plugin: mapPlugin
center: QtPositioning.coordinate(48.2351164, 6.8986936)
zoomLevel: 19
property real scale: map.scaleFactor()
onScaleChanged: {
console.log(">>> scale from map component", scale);
}
// function reimplemented from qdeclarativegeomapquickitem.cpp
function scaleFactor() {
return Math.pow(0.5, map.maximumZoomLevel - map.zoomLevel);
}
MapItemView {
model: myModel
delegate: MapQuickItem {
anchorPoint.x: myRect.width / 2
anchorPoint.y: myRect.height / 2
width: myRect.width
height: myRect.height
zoomLevel: map.maximumZoomLevel // set the zoomLevel (1:1 scale)
coordinate: QtPositioning.coordinate(model.latitude, model.longitude)
sourceItem: Rectangle {
id: myRect
readonly property int radius: 50
property real scale: root.map.scale
onScaleChanged: {
myCanvas.requestPaint();
}
width: radius * 2
height: radius * 2
color: "transparent"
Canvas {
id: myCanvas
anchors.fill: parent
onPaint: {
var width = myRect.width;
var height = myRect.height;
var centreX = width / 2;
var centreY = height / 2;
var ctx = getContext("2d");
ctx.reset();
if (scale > 0.1) {
ctx.fillStyle = "blue";
ctx.globalAlpha = 1;
ctx.beginPath();
ctx.moveTo(centreX, centreY);
ctx.arc(centreX, centreY, myRect.radius, 0, Math.PI * 2, false);
ctx.closePath();
ctx.fill();
}
}
}
}
}
}
}
}
轉載請註明出處,本文鏈接:https://www.uj5u.com/ruanti/418535.html
標籤:
下一篇:從資源檔案匯入QML模塊
