从C++实例化QML



我有两个类,MyApp和MyAppView。MyApp类将包含其他类,实现将在这里。(您可以称之为Manager类或System类(。MyAppView类只与main.qml交互,就像它会有很多"Q_PROPERTY"一样。我想你明白这一点。我不希望我的应用程序会有"Q_PROPERTY"ies。

场景如下:;

//------------------------------------
//---------------------------main.cpp
#include <QGuiApplication>
#include <QQmlApplicationEngine>
#include "myapp.h"
#include "myappview.h"
int main(int argc, char *argv[])
{
QGuiApplication app(argc, argv);
qmlRegisterType<MyAppView>("org.myappview", 1, 0, "MyAppView");
QQmlApplicationEngine engine;
engine.load(QUrl(QStringLiteral("qrc:/qml/main.qml")));
if (engine.rootObjects().isEmpty())
return -1;
MyApp myApp;
return app.exec();
}

//------------------------------------
//---------------------------myappview.h
#include <QObject>
class MyAppView : QObject
{
Q_OBJECT
Q_PROPERTY(QString myString READ getMyString NOTIFY myStringChanged)
public:
MyAppView();
QString getMyString() { return m_myString; }
void setMyString(QString newString)
{
m_myString = newString;
emit myStringChanged;
}
signals:
void myStringChanged();
private:
QString m_myString;
}

//------------------------------------
//---------------------------main.qml
import QtQuick 2.0
import QtQuick.Window 2.0
import org.myappview 1.0
Window {
visible: true
MyAppView {
id: backend
}
Text {
text: qsTr(backend.myString)
}
}

//------------------------------------
//---------------------------myapp.h
#include <QObject>
#include "myappview.h"
class MyApp : QObject
{
Q_OBJECT
public:
MyApp();
private:
MyAppView appView;
void changeMyStringInAppView()
{
// This will automatically update main.qml
appView.setMyString("This is new string");
}
}

此外,可以从MyApp访问现有的QML实例,而不是从MyApp实例化QML。所以重点是从Manager类实例化或访问View类,这样我就可以轻松地控制它。也许在某些方面,我的逻辑是错误的。请告诉我是不是。我同意所有的建议。

代码中的问题是MyAppMyAppView与QML中创建的不同,因此如果更新appView文本,它将不会反映在backend文本中,因此,解决方案是用setContextProperty()将对象从MyApp暴露给QML,并调用一个函数来建立在QML中创建的MyAppView(请记住,只创建一个MyApp,但您会遇到同样的问题(

// myappview.h
#ifndef MYAPPVIEW_H
#define MYAPPVIEW_H
#include <QObject>
class MyAppView : public QObject
{
Q_OBJECT
Q_PROPERTY(QString myString READ getMyString NOTIFY myStringChanged)
public:
explicit MyAppView(QObject *parent = nullptr) : QObject(parent)
{}
QString getMyString() const { return m_myString; }
void setMyString(const QString & newString)
{
if(m_myString != newString){
m_myString = newString;
emit myStringChanged();
}
}
signals:
void myStringChanged();
private:
QString m_myString;
};
#endif // MYAPPVIEW_H
// myapp.h
#ifndef MYAPP_H
#define MYAPP_H
#include "myappview.h"
#include <QObject>
class MyApp : public QObject
{
Q_OBJECT
public:
explicit MyApp(QObject *parent = nullptr) : QObject(parent),
appView(nullptr)
{}
Q_INVOKABLE void setAppView(MyAppView *value){
appView = value;
}
void changeMyStringInAppView()
{
if(appView)
appView->setMyString("This is new string");
}
private:
MyAppView *appView;
};
#endif // MYAPP_H
// main.cpp
#include "myapp.h"
#include "myappview.h"
#include <QGuiApplication>
#include <QQmlApplicationEngine>
#include <QQmlContext>
#include <QTimer>
int main(int argc, char *argv[])
{
QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
QGuiApplication app(argc, argv);
qmlRegisterType<MyAppView>("org.myappview", 1, 0, "MyAppView");
MyApp myapp;
QTimer::singleShot(1000, &myapp, &MyApp::changeMyStringInAppView);
QQmlApplicationEngine engine;
engine.rootContext()->setContextProperty("myapp", &myapp);
engine.load(QUrl(QStringLiteral("qrc:/main.qml")));
if (engine.rootObjects().isEmpty())
return -1;
return app.exec();
}
// main.qml
import QtQuick 2.9
import QtQuick.Window 2.2
import org.myappview 1.0
Window {
visible: true
width: 640
height: 480
title: qsTr("Hello World")
MyAppView {
id: backend
}
Text {
text: qsTr(backend.myString)
}
Component.onCompleted: myapp.setAppView(backend)
}

最新更新