Einführung
QML-Elemente können durch Standard-JavaScript sowohl inline als auch über mitgelieferte .js-Dateien erweitert werden. Die Elemente können auch nahtlos in C++-Komponenten integriert und erweitert werden, die das Qt-Framework verwenden.
Werfen wir einen Blick auf die wichtigsten technischen Punkte und Methoden, die wir verwendet haben. Hier werden wir einige Beispiele und Grundlagen für die Interaktion zwischen unserem Qt-Code und QML-Objekten demonstrieren.

Wo speichern?

setSource(QUrl::fromLocalFile(„:/map“))
Wie man QML einbettet
_qml_view = new QQuickView();
QWidget* container = QWidget::createWindowContainer(_qml_view, this);
container->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
_ui->qml_canvas_layout->addWidget(container);
_qml_view->setSource(QUrl::fromLocalFile(":/map"));
_qml_view = new QQuickView();
QWidget* container = QWidget::createWindowContainer(_qml_view, this);
container->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
_ui->qml_canvas_layout->addWidget(container);
_qml_view->setSource(QUrl::fromLocalFile(":/map"));
import QtQuick 2.0
Rectangle {
id: main
color: "#FF0000"
width: 200
height: 100
}
import QtQuick 2.0
Rectangle {
id: main
color: "#FF0000"
width: parent.width
height: parent.height
}

Map plugin
import QtQuick 2.0
import QtLocation 5.11
import QtPositioning 5.11
Rectangle {
id: main
width: parent.width
height: parent.height
Plugin {
id: mapPlugin
name: "esri"
}
Map {
id: mapView
objectName: "mapView"
anchors.fill: parent
plugin: mapPlugin
center: QtPositioning.coordinate(59.9386, 30.3141)
zoomLevel: 15
}
}

Wie wir die Karte bearbeiten können
auto map_view = _qml_view->rootObject()->findChild<QQuickItem*>("mapView");
auto coordinates = map_view->property("center").value();
coordinates.setLatitude(coordinates.latitude() + 0.02);
map_view->setProperty("center", QVariant::fromValue(coordinates));

Um die Koordinaten zu erhalten, fügen wir eine Struktur und eine Methode zu QML hinzu:
MouseArea {
id: mapViewMouseArea
anchors.fill: parent
propagateComposedEvents: true
hoverEnabled: true
}
function getMousePosition() {
return mapView.toCoordinate(Qt.point(mapViewMouseArea.mouseX, mapViewMouseArea.mouseY));
}
std::tuple<float, float> MainWindow::getMouseCoordinates()
{
auto map_view = _qml_view->rootObject()->findChild<QQuickItem*>("mapView");
QVariant result;
bool invoke_result = QMetaObject::invokeMethod(
map_view,
"getMousePosition",
Qt::DirectConnection,
Q_RETURN_ARG(QVariant, result)
);
if (!invoke_result)
std::make_tuple(0.f, 0.f);
QGeoCoordinate coordinates = result.value();
return std::make_tuple(coordinates.latitude(), coordinates.longitude());
}

onCenterChanged: {
qmlReceiver.centerChanged(center);
}
class QMLReceiver : public QObject
{
Q_OBJECT
public:
Q_INVOKABLE void centerChanged(QGeoCoordinate coordinate)
{
emit centerChangedSignal(coordinate.latitude(), coordinate.longitude());
}
signals:
void centerChangedSignal(float lat, float lon);
};
_qml_receiver = new QMLReceiver();
_qml_view->rootContext()->setContextProperty("qmlReceiver", _qml_receiver);
QObject::connect(
_qml_receiver,
&QMLReceiver::centerChangedSignal,
this,
&MainWindow::onCenterChanged
);

Um Objekte auf der Karte darzustellen, verwenden wir das Model-View-Konzept. Fügen wir dies dem Map-Objekt hinzu:
MapItemView {
model: markerModel
delegate: mapComponent
}
Component {
Component {
id: mapComponent
MapQuickItem {
id: marker
anchorPoint.x: image.width / 2
anchorPoint.y: image.height
coordinate: positionValue
property string identifier: identifierValue
property string name: nameValue
property string icon: iconValue
sourceItem: Image {
id: image
source: icon;
}
MouseArea {
id: mouseArea
anchors.fill: parent
hoverEnabled: true
drag.target: parent
onClicked: {
qmlReceiver.markerClicked(identifier, name, coordinate);
}
}
}
}
- positionValue, von dem die Koordinaten des Objekts übernommen werden;
- identifierValue und nameValue, die es uns ermöglichen, das Objekt zu identifizieren;
- iconValue, wo sich das Symbol des Objekts befindet.
enum MarkerRoles
{
positionRole = Qt::UserRole + 1,
identifierRole = Qt::UserRole + 2,
nameRole = Qt::UserRole + 3,
iconRole = Qt::UserRole + 4,
};
QHash<int, QByteArray> MarkerModel::roleNames() const
{
QHash<int, QByteArray> roles;
roles[positionRole] = "positionValue";
roles[identifierRole] = "identifierValue";
roles[nameRole] = "nameValue";
roles[iconRole] = "iconValue";
return roles;
}
QVariant MarkerModel::data(const QModelIndex& index, int role) const
{
if (index.row() < 0 || index.row() >= _markers.count())
return QVariant();
if (role == MarkerModel::positionRole)
return QVariant::fromValue(_markers[index.row()]._position);
else if (role == MarkerModel::identifierRole)
return QVariant::fromValue(_markers[index.row()]._identifier);
else if (role == MarkerModel::nameRole)
return QVariant::fromValue(_markers[index.row()]._name);
else if (role == MarkerModel::iconRole)
return QVariant::fromValue(_markers[index.row()]._icon);
return QVariant();
}

Wichtig zu erwähnen: In unserem Beispiel haben wir Icons aus dem Internet verwendet, aber Sie können jederzeit Ihre lokalen Dateien verwenden. Beachten Sie, dass Sie keine Datei mit demselben Namen, aber anderem Inhalt verwenden können. Damit sich das Symbol auf der Karte ändert, muss auch der Dateiname anders sein.
Sie können das Quellarchiv herunterladen, indem Sie auf den folgenden Link klicken.