Gibt es eine Möglichkeit, Klassen in C ++ eine direkte visuelle Darstellung in QML zu geben?C++

Programme in C++. Entwicklerforum
Anonymous
 Gibt es eine Möglichkeit, Klassen in C ++ eine direkte visuelle Darstellung in QML zu geben?

Post by Anonymous »

Ich entwickle eine GIS-bezogene Anwendung, in der ich eine Karte habe, und ich möchte Kreise darauf setzen. Dafür benutze ich QML. Die Architektur lautet: < /p>
1-GeometrikFigur.H: Grenzfläche für gemeinsame geometrische Figuren < /p>
2- Kreis.H und Kreis.CPP: Subklassen von Geometrieb und Geometricform.H und GEOMETRICRICRICN. QabstractListModel zum Speichern der auf der Karte gezeichneten geometrischen Figuren < /strong>. Ich möchte, dass mein C ++-Klassenkreis eine visuelle Darstellung hat, nicht nur für die Backend-Verarbeitung.// main.cpp
#include
#include
#include "Circle.h"
#include "GeometricFigureList.h"
#include

int main(int argc, char *argv[])
{
QGuiApplication app(argc, argv);
QQmlApplicationEngine engine;

// Register circle class for use in QML
qmlRegisterType("MiApp.Figures", 1, 0, "Circle");

// Register model
ListaFigurasGeometricas figureList;
engine.rootContext()->setContextProperty("figureList", &figureList);

QObject::connect(
&engine,
&QQmlApplicationEngine::objectCreationFailed,
&app,
[]() { QCoreApplication::exit(-1); },
Qt::QueuedConnection);

engine.loadFromModule("Test", "Main");

return app.exec();
}

< /code>
// Main.qml
import QtQuick 2.15
import QtQuick.Window 2.15
import QtQuick.Controls 2.15
import QtLocation 6.8
import QtPositioning 6.8
import MiApp.Figures 1.0
import "./" // Importa los componentes CircleElement, etc.

Window {
width: 800
height: 600
visible: true
title: qsTr("Map with elements")

// Propiedad para almacenar el tipo de elemento seleccionado:
property string currentElementType: "circle" // Valor por defecto

Column {
anchors.fill: parent

// Fila con botones para seleccionar el tipo de elemento
Row {
spacing: 10
padding: 10

Button {
text: "Circle"
onClicked: currentElementType = "circle"
}
}

// MapView que muestra el mapa y donde se crearán los elementos
MapView {
id: mapView
anchors.horizontalCenter: parent.horizontalCenter
width: parent.width
height: parent.height - 60
map.plugin: Plugin { name: "osm" }
map.center: QtPositioning.coordinate(40.416775, -3.703790)
map.zoomLevel: 10

// Capturamos el click en el mapa para crear el elemento seleccionado.
MouseArea {
anchors.fill: parent
onClicked: function(mouseEvent) {
var coord = mapView.map.toCoordinate(Qt.point(mouseEvent.x, mouseEvent.y))
// Aquí creas el objeto dinámicamente, etc.

// Crear dinámicamente el elemento en el mapa.
if (currentElementType === "circle") {
var cir = circleComponent.createObject(mapView.map,{radius:100000, center:coord})
mapView.map.addMapItem(cir)
figureList.addData(cir.getInternalCircle())
}
}
}
}
}

// Componentes para instanciar dinámicamente cada tipo de elemento
Component {
id: circleComponent
Circle {
}
}
}

< /code>
// Circle.qml
import QtQuick 2.15
import QtLocation 6.8
import QtPositioning 6.8
import MiApp.Figures 1.0

MapCircle{
id: myWrapper

color: "red"

// Si usase circle directamente, QML no sabría como pintarlo
// He de tener un wrapper, MapCircle, para poder usarlo.
Circle{
id: myCircle
}

function getInternalCircle(){
myCircle.setRadius(myWrapper.radius)
myCircle.setCenter(myWrapper.center)
return myCircle
}

onRadiusChanged: myCircle.setRadius(myWrapper.radius)
onCenterChanged: myCircle.setCenter(myWrapper.center)

}

< /code>
//GeometricFigureList.cpp
#include "GeometricFigureList.h"

GeometricFigureList::GeometricFigureList(QObject *parent)
: QAbstractListModel(parent) {}

int GeometricFigureList::rowCount(const QModelIndex &parent) const {
Q_UNUSED(parent)
return m_list.size();
}

QVariant GeometricFigureList::data(const QModelIndex &index, int role) const {
if (!index.isValid() || index.row() >= m_list.size())
return QVariant();

const GeometricFigures *figure = m_list.at(index.row());
if (role == NombreRole)
return figure->name();
else if (role == TipoRole)
return figure->tipo();

return QVariant();
}

bool GeometricFigureList::setData(const QModelIndex &index, const QVariant &value, int role) {
if (!index.isValid() || index.row() >= m_list.size())
return false;

GeometricFigures *figure = m_list.at(index.row());

if (role == NombreRole)
figure->setName(value.toString());
else if (role == TipoRole)
figure->setType(value.toInt());
else
return false;

emit dataChanged(index, index, {role});
return true;
}

void GeometricFigureList::addData(GeometricFigures *figure) {
beginInsertRows(QModelIndex(), m_list.size(), m_list.size());
m_list.append(figure);
endInsertRows();
}

QHash GeometricFigureList::roleNames() const {
QHash roles;
roles[NombreRole] = "name";
roles[TipoRole] = "tipo";
return roles;
}

< /code>
#ifndef GEOMETRICFIGURELIST_H
#define GEOMETRICFIGURELIST_H

#include
#include "GeometricFigures.h"

class GeometricFigureList : public QAbstractListModel {
Q_OBJECT
public:
explicit GeometricFigureList(QObject *parent = nullptr);

enum Roles {
NombreRole = Qt::UserRole + 1,
TipoRole
};

int rowCount(const QModelIndex &parent = QModelIndex()) const override;
QVariant data(const QModelIndex &index, int role) const override;
bool setData(const QModelIndex &index, const QVariant &value, int role) override;

Q_INVOKABLE void addData(GeometricFigures *figure);

QHash roleNames() const override;

private:
QList m_list;
};

#endif // LISTAFIGURASGEOMETRICAS_H

< /code>
//Circle.cpp

#include "Circle.h"

Circle::Circle(QQuickItem *parent) : GeometricFigures(parent), m_radio(0.0) {}

double Circle::radio() const { return m_radio; }
void Circle::setRadius(double r) {
if (m_radio != r) {
m_radio = r;
emit radioChanged();
}
}

QGeoCoordinate Circle::center() const{
return m_center;
}
void Circle::setCenter(QGeoCoordinate c){
m_center = c;
}

QString Circle::name() const { return "Circle"; }
void Circle::setName(const QString &) {}

int Circle::tipo() const { return 1; }
void Circle::setType(int) {}

< /code>
#ifndef CIRCLE_H
#define CIRCLE_H

#include "GeometricFigures.h"
#include

class Circle : public GeometricFigures {
Q_OBJECT
Q_PROPERTY(double radio READ radio WRITE setRadius NOTIFY radioChanged)
Q_PROPERTY(QGeoCoordinate center READ center WRITE setCenter NOTIFY centerChanged)

public:
explicit Circle(QQuickItem *parent = nullptr);

Q_INVOKABLE double radio() const;
Q_INVOKABLE void setRadius(double r);

Q_INVOKABLE QGeoCoordinate center() const;
Q_INVOKABLE void setCenter(QGeoCoordinate r);

QString name() const override;
void setName(const QString &) override ;

int tipo() const override;
void setType(int) override;

signals:
void radioChanged();
void centerChanged();

private:
double m_radio;
QGeoCoordinate m_center;
};

#endif // CIRCLE_H

< /code>
#ifndef FIGURASGEOMETRICAS_H
#define FIGURASGEOMETRICAS_H

#include
#include

class GeometricFigures : public QQuickItem {
Q_OBJECT
Q_PROPERTY(QString name READ name WRITE setName NOTIFY nameChanged)
Q_PROPERTY(int tipo READ tipo WRITE setType NOTIFY typeChanged)

public:
explicit GeometricFigures(QQuickItem *parent = nullptr) : QQuickItem (parent) {}

virtual QString name() const = 0;
virtual void setName(const QString &) = 0;

virtual int tipo() const = 0;
virtual void setType(int) = 0;

signals:
void nameChanged();
void typeChanged();
};

#endif // FIGURASGEOMETRICAS_H

< /code>
cmake_minimum_required(VERSION 3.16)

project(Test VERSION 0.1 LANGUAGES CXX)

set(CMAKE_CXX_STANDARD_REQUIRED ON)

find_package(Qt6 REQUIRED COMPONENTS Quick Positioning)

qt_standard_project_setup(REQUIRES 6.8)

qt_add_executable(appTest
main.cpp
)

qt_add_qml_module(appTest
URI Test
VERSION 1.0
QML_FILES
Main.qml
QML_FILES Circle.qml
SOURCES GeometricFigures.h
SOURCES Circle.h Circle.cpp
SOURCES GeometricFigureList.h GeometricFigureList.cpp
)

# Qt for iOS sets MACOSX_BUNDLE_GUI_IDENTIFIER automatically since Qt 6.1.
# If you are developing for iOS or macOS you should consider setting an
# explicit, fixed bundle identifier manually though.
set_target_properties(appTest PROPERTIES
# MACOSX_BUNDLE_GUI_IDENTIFIER com.example.appTest
MACOSX_BUNDLE_BUNDLE_VERSION ${PROJECT_VERSION}
MACOSX_BUNDLE_SHORT_VERSION_STRING ${PROJECT_VERSION_MAJOR}.${PROJECT_VERSION_MINOR}
MACOSX_BUNDLE TRUE
WIN32_EXECUTABLE TRUE
)

target_link_libraries(appTest
PRIVATE Qt6::Quick
PRIVATE Qt6::Positioning
)

include(GNUInstallDirs)
install(TARGETS appTest
BUNDLE DESTINATION .
LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
)

< /code>
The problem with that is that I have to use MapCircle as a wrapper and I want a solution more like:
Circle{
id: myCircle

delegate: MapCircle{
id: myCircleVisualRepresentation
color: "red"
}
}
< /code>
That way I could do:
var cir = circleComponent.createObject(mapView.map)
cir.setRadius(10000)
cir.setCenter(coords)
mapView.map.addMapItem(cir)
figureList.addData(cir)
< /code>
Without requesting the wrapper inner component.
But that is not possible, there is no delegate property in the registered version of Circle class.
So the question is: Is there any way to give C++ registered classes a visual representation in QML?
Thanks and pardon my english.

Quick Reply

Change Text Case: 
   
  • Similar Topics
    Replies
    Views
    Last post