Как я могу получить доступ к своим свойствам объекта Window из С++ при использовании QQmlApplicationEngine?
Я пытался изучить QtQuick для создания графического интерфейса, но мне было трудно понять, как взаимодействовать с объектами QML из части С++ моей тестовой программы.
Вот мой простой файл QML:
import QtQuick 2.2
import QtQuick.Window 2.1
Window {
id: mainWindow
visible: true
width: 800
height: 800
color: "#FFFF0000"
MouseArea {
anchors.fill: parent
onClicked: Qt.quit()
}
Rectangle {
id: testRect
width: 100
height: 100
anchors.centerIn: parent
color: "#FF0000FF"
}
}
Вот базовый файл С++, который пришел с ним (автоматически сгенерированный QtCreator):
#include <QGuiApplication>
#include <QQmlApplicationEngine>
int main(int argc, char *argv[])
{
QGuiApplication app(argc, argv);
QQmlApplicationEngine engine;
engine.load(QUrl(QStringLiteral("qrc:///main.qml")));
return app.exec();
}
Моя проблема в том, что я понятия не имею, как получить доступ к моему QML-объекту Window, и в результате я не могу изменить какие-либо его свойства или свойства своих детей! Эта часть документации QtQuick показывает два метода доступа к объектам QML из кода С++, но ни один из них, похоже, не применяется к этой схеме загрузки "QQmlApplicationEngine". Я также видел, что люди используют такие вещи, как "QApplicationViewer" и "QDeclaritiveView", но я не могу найти их в официальной документации вообще.
Меня сильно расстраивает QtQuick; "простота" QML кажется утраченной в море противоречивой документации и запутанном интерфейсе между С++ и QML. Есть ли в любом случае для меня доступ к моим объектам QML при использовании метода QQmlApplicationEngine? Я попытался использовать "QuickView", но, похоже, он не работает с объектами Window QML.? Является ли QQmlApplicationEngine полезным только для приложений только для QML в одном файле? До сих пор каждый фрагмент документации и учебника, который я прочитал, показал что-то другое.
Любая помощь или разъяснение будут оценены. В идеале я хотел бы узнать, как получить доступ и изменить объекты QML (например, "mainWindow", "testRect" и другие объекты в других файлах) через мой код на С++.
Ответы
Ответ 1
Превращение моего комментария в правильный ответ: обычно это делается двумя способами:
-
Получите корневой объект вашей сцены QML через представление, если вы используете непосредственно QQuickView
или просто QQmlApplicationEngine
.
-
Этот следующий шаг может быть опущен для корневых объектов, но для "объектов qml" в общем случае вам нужно будет objectName property, а затем вы можете найти любых детей со следующим методом:
QList QObject:: findChildren (const QString и name = QString(), Qt:: FindChildOptions options = Qt:: FindChildrenRecursively) const
сторона С++
#include <QGuiApplication>
#include <QQmlApplicationEngine>
#include <QDebug>
int main(int argc, char *argv[])
{
QGuiApplication app(argc, argv);
QQmlApplicationEngine engine;
engine.load(QUrl(QStringLiteral("qrc:///main.qml")));
// Step 1: get access to the root object
QObject *rootObject = engine.rootObjects().first();
QObject *qmlObject = rootObject->findChild<QObject*>("mainWindow");
// Step 2a: set or get the desired property value for the root object
rootObject->setProperty("visible", true);
qDebug() << rootObject->property("visible");
// Step 2b: set or get the desired property value for any qml object
qmlObject->setProperty("visible", true);
qDebug() << qmlObject->property("visible");
return app.exec();
}
Смотрите документацию для набора свойств и зайдите в официальную документацию:
bool QObject:: setProperty (const char * name, const QVariant и значение)
и
QVariant QObject:: property (const char * name) const
Хорошо, теперь мы более или менее выполняем действия на стороне С++.
Сторона QML
Вам также нужно будет иметь свойство objectName
для ваших объектов qml, если вы хотите получить доступ к более чем одному корневому элементу следующим образом:
import QtQuick 2.2
import QtQuick.Window 2.1
Window {
id: mainWindow
objectName: "mainWindow"
...
}
Это может быть сделано аналогичным образом для любого объекта QML. Ключ здесь "objectName". Вы можете опустить это для корневого объекта, так как сторона С++ получает объект root напрямую, но поскольку вы ссылаетесь на объекты QML в своем вопросе, я предполагаю, что вы хотели бы его решить в целом. Как только вы захотите сделать то же самое для любого объекта QML, то есть включая детей, вам нужно будет использовать свойство objectName.