【问题标题】:declare global property in QML for other QML files在 QML 中为其他 QML 文件声明全局属性
【发布时间】:2013-02-21 20:52:12
【问题描述】:

我想在配置文件中声明一个全局属性并在其他文件中使用它。例如声明mainbg 在:

Style.qml

property color mainbg: 'red'

并在其他 QML 文件中使用它(如 view.qmlmain.qml)。我怎样才能完成这项工作?

【问题讨论】:

    标签: qt variables scope qml global-variables


    【解决方案1】:

    使用 QML 单例。

    请参考this page上的“方法2” -- 丑陋的QTBUG-34418 cmets 是我的。

    这些是你需要的:

    Style.qml

    pragma Singleton
    import QtQuick 2.0
    QtObject {
        property color mainbg: 'red'
    }
    

    qmldir

    此文件必须与单例 .qml 文件(在我们的示例中为 Style.qml)位于同一文件夹中,否则您必须提供它的相对路径。 qmldir 可能还需要包含在 .qrc 资源文件中。更多关于 qmldir 文件的信息可以在here找到。

    # qmldir
    singleton Style Style.qml
    

    如何参考

    import QtQuick 2.0
    import "."  // this is needed when referencing singleton object from same folder
    Rectangle {
        color: Style.mainbg  // <- there it is!!!
        width: 240; height 160
    }
    

    这种方法从 Qt5.0 开始可用。即使引用同一文件夹中的 QML 单例,您也需要一个文件夹 import 语句。如果是同一个文件夹,请使用:import "." 这是我在 qt-project 页面上记录的错误(参见 QTBUG-34418,单例需要显式导入才能加载 qmldir 文件)。

    【讨论】:

    • 为什么不只是一个简单的.pragma library javascript 文件?
    • 正如tonytony 回答的那样,.pragma library 不保证共享实例。单例让您可以即时更改全局样式,并更新所有绑定以显示相同的字体、颜色等。
    • 几年后,我盲目地建议在专用样式类中使用 Q_PROPERTY,而不是滥用 QML 层来满足这种需求,它更可靠
    【解决方案2】:

    基本上,如果您不需要属性绑定(如果您的值是常量并且不需要在更改时通知),您可以在 Javascript 共享库中定义它,如下所示:

    // MyConstants.js
    .pragma library
    var mainbg = "red";
    

    并像这样在 QML 中使用它:

    import "MyConstants.js" as Constants
    
    Rectangle {
         color: Constants.mainbg;
    }
    

    但这不好的一面是: - 没有强类型(JS 并不真正了解类型),所以即使它不是颜色,你也可以放置任何东西。 - 如果您更改mainbg,使用它的项目将不会收到有关更改的通知,并将保留旧值

    因此,如果您需要类型检查和绑定/更改通知,只需在 main.qml 中将您的属性声明为根对象的成员,它就可以从 QML 应用程序中的任何地方访问,因为该属性实际上会直接注册到 Qml Context 对象中,根据定义,它是全局的。

    希望对你有帮助。

    【讨论】:

      【解决方案3】:

      您可以创建一个 js 文件并将其导入到所有必须使用此属性的文件中。

      js文件:

      //Note: you only need '.pragma library' if you are planning to
      //change this variable from multiple qml files
      .pragma library
      var globalVariable = 20;
      

      qml 文件:

      import "test.js" as Global
      
      Rectangle {
        id: main
        width: 300; height: 400
      
        Component.onCompleted: {
          console.log( Global.globalVariable)
          //you can also change it
          Global.globalVariable = 5
        }
      }
      

      【讨论】:

      • 别忘了把#pragma library放在那里。
      • 我必须注意到.pragma library 允许 JS文件被多个QML文件使用,但不保证只有一个库的实例。我刚刚在我的应用程序中遇到了严重的错误,这是由于我尝试使用 JS 库作为全局状态容器。
      【解决方案4】:

      添加一些对@pixelgrease 答案的贡献,我发现了另一种不需要相对路径import "." 的技术,解决了错误QTBUG-34418。这很有用,尤其是当一个 qmldir 和单例类位于与使用单例的 qml 文件不同的位置时。该技术需要在树结构中定义一个适当的模块:然后通过使用QmlEngine::addImportPath(moduleParentPath) 将模块的父路径添加到 QML 引擎来解析模块。例如:

      qml/
      ├── <ModuleName>/
      │ ├── <ClassName>.qml
      │ ├── qmldir
      

      在 main.cpp 中你有:

      QQmlApplicationEngine engine;
      engine.addImportPath("qrc:/qml");    // Can be any directory
      engine.load("qrc:/qml/main.qml");
      

      如果使用资源,qml.qrc:

      <RCC>
       <qresource prefix="/">
            (...)
       <file>qml/main.qml</file>
       <file>qml/MySingletons/MySingleton.qml</file>
       <file>qml/MySingletons/qmldir</file>
       </qresource>
      </RCC>
      

      在 qmldir 中:

      module MySingletons
      singleton MySingleton 1.0 MySingleton.qml
      

      在 main.qml 或其他目录中的任何其他 qml 文件中:

      import MySingletons 1.0
      

      然后你像往常一样使用 MySingleton 类。我将示例 MySingletonWithModule.7z 附加到 bug QTBUG-34418 以供参考。

      【讨论】:

        【解决方案5】:

        在 main 中添加此属性,您可以在任何 qml 中访问它,这可能不是正确的方法,但这是可行的。

        或者,如果您想对属性进行分组,请将它们添加到 qml 在 main 中包含该 qml 并提供一个 id,现在您可以使用该 id 访问此属性

        main.qml

         Item{
         width:10
         height:10
        
         Model{
         id:globdldata
         }
        
        
        
         }
        

        模型.qml

        Item {
        
        property color mainbg: 'red'
        
        }
        

        你可以在任何地方使用 globdldata.mainbg

        【讨论】:

          【解决方案6】:

          您始终可以创建一个新的 QML 对象文件,其中包含您希望跨 qml 文件共享的属性。只需以与任何 QML 对象相同的方式导入它,您就可以访问属性。现在,如果您希望能够修改这些属性并在实例之间共享更改,事情会变得更加棘手,您很可能需要使用 .pragma 库 js 文件的某种解决方案。除非您想编写某种 C++ 替代方案。

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 2014-12-31
            • 1970-01-01
            • 1970-01-01
            • 2021-06-25
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多