【问题标题】:Setting context property for multiple qml files为多个 qml 文件设置上下文属性
【发布时间】:2018-03-21 09:39:36
【问题描述】:

我有一个 main.qml,里面有两个横幅(titlebanner 和 bottombanner),如下所示。

Window {
    id: main
    visible: true

    Image {
        source: "qrc:/banner.png"
        anchors.fill: parent
    }

    TitleBanner {
        x:0
        y:10
    }

    BottomBanner {
        x:0
        y:420
    }
}

在 TitleBanner.qml 中,我有以下代码

Item {
    Rectangle {
        id : id_title_banner

        property real value : titlebanner.title

        Image {
            source: "qrc:/banner_title.png";
        }

        //todo:: some animation stuffs on 'value' later
    }
}

在 BottomBanner.qml 中,我有以下代码

Item {
    Rectangle {
        id : id_bottom_banner

        property real value : bottombanner.title

        Image {
            source: "qrc:/banner_bottom.png";
        }

        //todo:: some animation stuffs on 'value' later
    }
}

在 C++ 方面,我为标题横幅和底部横幅保留了两个单独的对象(为了以后的灵活性)。我设置了根上下文属性以将标题横幅对象从 C++ 公开到 qml,如下所示

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

   //create title banner object
   CTitleBanner *objTitleBanner = new CTitleBanner();

   //create bottom banner object
   CBottomBanner *objBottomBanner = new CBottomBanner();

   QQmlApplicationEngine engine;
   engine.rootContext()->setContextProperty("titlebanner", objTitleBanner);

   engine.load(QUrl(QStringLiteral("qrc:/main.qml")));

   return app.exec();

}

我的问题是,我们如何分别为 titlebanner 和 bottombanner qml 文件设置上下文属性,而不是将其设置为根上下文?我担心的是,如果以后有更多横幅出现,我将其设置为 rootContext。这是一种正确的做法吗?我们如何为每个横幅创建单独的上下文?

【问题讨论】:

  • "它替换了上面的上下文属性。"可以?我不想尝试。如果是这样的话。你为什么不创建一个QObject contextData,它有两个属性:titlebannerbottombanner,你将它们设置为(可能是巧合?)你的两个原始横幅对象。但是我认为我最初的问题的答案应该是“不”。
  • @derM,对不起,我的问题有更正,我已经编辑了相同的内容。是的。你的观点是正确的,它不会取代我之前尝试过的上下文。请查看我编辑的问题。
  • 我没有收到你的新问题。会有多少条横幅? C++ 会对此产生什么影响?由于 QML 更灵活,您应该努力使您的 C++ 部分尽可能不可变。在 C++ 中创建一个稳定 数据模型,仅在 QML 中实现视觉表示的魔力。如果例如,您可能会在 C++ 中创建某种内容模型。可能需要访问数据库。 C++ 部分应该不知道视图中有什么
  • @derM,在上面的示例中,我正在为根上下文设置 contextProperty。所以我可以从我所有的 qml 文件中访问横幅对象。例如,在 BottomBanner.qml 文件中,我也可以访问“objTitleBanner”。我在想这是一种首选的方式吗?稍后,我计划添加更多横幅(比如大约 20 个横幅)。所以最后我们可以从任何 qml 文件中访问所有横幅对象。我不知道这是不是 qt 的开销。是这样吗?所以我在想我们可以设置一个特定于 qml 文件的上下文。例如,从 TitleBanner.qml 我只能访问“objTitleBanner”。
  • 设置上下文属性实际上只是将属性设置到 QML 对象树的最根目录。这意味着,QML 将遵循常规的名称解析算法(查看当前范围,查看文件根范围,查看实例化该文件的文件的根范围等,直到它到达根上下文 - 或失败)。在一个范围内,查找应该很快,因为它(afaik)被实现为某种地图。拥有 20 个上下文属性比尝试从深度嵌套的对象中访问它的问题要小。

标签: qt qml


【解决方案1】:

你的假设:

它替换了上面的上下文属性。

错了:

// in main.cpp
QObject* obj1 = new QObject();
QObject* obj2 = new QObject();

engine.rootContext()->setContextProperty("obj1", obj1);
engine.rootContext()->setContextProperty("obj2", obj2);

qDebug() << "obj1" << obj1 << engine.rootContext()->contextProperty("obj1").value<QObject*>();
qDebug() << "obj2" << obj2 << engine.rootContext()->contextProperty("obj2").value<QObject*>();

// in main.qml
Component.onCompleted: console.log(obj1, obj2)

// output:
obj1 QObject(0x22d8c768) QObject(0x22d8c768)
obj2 QObject(0x22d8c778) QObject(0x22d8c778)
qml: QObject(0x22d8c768) QObject(0x22d8c778)

两个对象都在那里,具有正确的标识符。


就个人而言我不喜欢contextProperties,因为它们很容易被遮蔽等等。 - 我宁愿将我的 CPP 模型注册为单例,这样我就可以在我真正想要访问它们的地方导入它们。尽管这些单身人士也有缺点。 (例如qmlscene 将无法导入它们)

【讨论】:

  • 您的意思是使用 qmlRegisterType 注册您的模型并使用模型中的 setProperty 设置 qml 属性?我还计划用这个解决方案替换上下文属性。在我的情况下,我更喜欢将我的自定义类称为控制器并使用 qmlRegisterType 注册它并从我的自定义控制器类中设置属性。我有另一个与控制器类关联的模型类。
  • 没有。我的意思是用qmlRegisterSingleton 注册它,如果对象的性质确实是单例[在一个进程中]。如果不是,我会将其注册为可实例化类型(qmlRegisterType),但我也会在 QML 中创建实例(例如MySubViewSpecificNonSingletonModel { })——这些方法的缺点是,它更难模拟他们进行测试,例如qmlscene.
  • 但是,使用 C++ 中的setProperty 意味着,您的 C++ 部分需要对 QML 结构有深入的了解,您希望避免这种情况,因为您会失去灵活性。改变视图也意味着改变模型。 使用 setContextProperty 意味着您需要遵守命名约定以避免名称出现阴影。这可能会给第 3 方代码或同事带来问题。
  • “但是,使用 C++ 中的 setProperty 意味着,您的 C++ 部分需要对 QML 结构有深入的了解”,是的。我同意。但据我了解,这将使 C++ 和 Qt 之间有更多的解耦。我指的是链接zhieng.com/exposing-qml-object-pointer-to-cc。您建议哪种解决方案在 Qt 和 C++ 之间提供更多解耦逻辑?
  • 所以他所做的就是在 QML 中实例化一个对象。他对Component.onCompleted{ ... } 的态度很差。他应该公开一个属性,您可以将该对象绑定到该属性,但在内部它将调用setMyObject - 所以......好吧。其余的还可以。有点类似于QtQuick.Controls 2.x 中所做的:您在 C++ 中定义控件的行为内容,通过contentItem etc. 属性将可视化表示传递给 C++ 端。但是大多数部分是通过向 QML 提供设计人员可能选择绑定到的属性来完成的 - 而不是在 Items 中主动覆盖。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-02-27
  • 1970-01-01
  • 2016-01-09
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多