从另一个 QML 文件打开新的 QML 文件

Posted

技术标签:

【中文标题】从另一个 QML 文件打开新的 QML 文件【英文标题】:Open new QML file from Another QML file 【发布时间】:2020-11-23 15:40:52 【问题描述】:

当用户单击test1.qml 内的按钮时,我正在尝试打开test2.qml 文件。

我可以使用 qml StackLayoutStatic Loading 文件和使用 qml Loader 来做到这一点。

// main.qml
Window 
  width: 400
  height: 400

  StackLayout 
    id: myStack
    anchors.fill: parent
   
    Test1 
    Test2  
  


// Test1.qml 
Item 
  width: 400 
  height: 400

  Button 
    text: "Move Test2"
    onClicked: 
       myStack.currentIndex = 1 // Move to page 2
    
  


// Test2.qml 
Item 
  width: 400 
  height: 400

  Button 
    text: "Move Test1"
    onClicked: 
       myStack.currentIndex = 0 // Move to page 1
    
  

但是有没有一种方法可以在不使用 StackLayout 或 Loader 甚至静态包含文件并设置可见性的情况下从另一个 QML 文件打开 .qml 文件?

有没有办法可以使用 QT Quick C++ API 或直接从 QML 加载文件?

【问题讨论】:

"或直接来自 QML" -- 不清楚这意味着什么。 StackLayoutLoader 都是直接加载其他组件的 QML 方式。您到底在寻找什么? 也许您正在寻找 dynamically 从 JS 代码创建对象? 如果您使用堆栈布局,则很少有限制,例如堆栈中加载的视图无法查看全屏或超出其父级堆栈布局的范围。同样使用加载器并设置可见性,代码不可读。我可以在运行时使用加载器和加载视图。但在我们有任何其他选择之前,它也不能令人信服。 【参考方案1】:

我想你可能正在寻找这个: https://doc.qt.io/qt-5/qtqml-modules-qmldir.html

让我们看一下他们的示例代码:

//Style.qml with custom singleton type definition
pragma Singleton
import QtQuick 2.0

QtObject 
    property int textSize: 20
    property color textColor: "green"

上面是我们想要导入到其他 qml 文件中的自定义类型。

// qmldir declaring the singleton type
module CustomStyles
singleton Style 1.0 Style.qml

上面是我们放入 qmldir 文件的内容。您必须创建一个单独的模块,然后该模块将具有此 qmldir 文件。您必须使用 QtCreator 向导创建一个空文件并将其命名为 qmldir。这是 Qt 模块的一个特性。你说,“这是我的模块的名称,它在 Style.qml 中定义了这个类型”在那个 qmldir 文件中。这几乎就是它所做的一切。您可以在其中定义任意数量的 qml 类型。

// singleton type in use
import QtQuick 2.0
import CustomStyles 1.0

Text 
    font.pixelSize: Style.textSize
    color: Style.textColor
    text: "Hello World"

在这里,我们从 CustomStyles 模块导入样式,并在需要的地方使用它。

所以这里发生了什么

    创建了一个模块。一个模块基本上就是一个文件夹,里面有一个 .pro 文件和一个 qmldir 文件。您将使用 import 语句导入您的模块。您可能想使用TEMPLATE = subdirs 来创建一个包含多个模块的项目。

    Style.qml(仅作为示例)被创建,然后从该模块导出(设置为公共)。您使用模块中的 qmldir 文件设置为 public。

    在qml中你要导入qml文件到你里面做 import CustomStyles 1.0 或您在项目中使用的任何模块名称,

    然后您可以引用 qmldir 文件中定义的任何 QML 类型,因为它已设置为 public 并且您导入了模块。

因此,不要像在 C++ 中那样考虑 #include 文件,而是更像在 python 中导入模块,然后可以引用该模块中的任何公共类或函数。

如果您想进一步了解如何创建模块,请随时发表评论。您需要创建一个模块,因为导入语句导入模块而不是单个文件。导入模块可以访问从 qmldir 文件中的模块导出的所有文件。

【讨论】:

【参考方案2】:

您可以使用JS创建QML对象,参见示例https://doc.qt.io/qt-5/qtqml-javascript-dynamicobjectcreation.html#creating-a-component-dynamically

【讨论】:

【参考方案3】:

首先,我认为不可能以不同于使用 Loader 或静态导入的方式加载 QML 文件。

我能想到的唯一其他方法是直接使用 QML 字段作为一个简单的组件,当它在项目中的相同前缀中时。

所以为了解释: 如果您有一个简单的项目,其中所有 QML 文件都在同一个前缀中。

当您拥有此结构中的所有文件时,您可以直接在此处动态使用其他 QMl 文件。据我所知,这是有效地做到这一点的唯一方法。

代码如下: main.qml

import QtQuick 2.15
import QtQuick.Controls 2.12
import QtQuick.Layouts 1.3

Window 
  width: 400
  height: 400

  StackLayout 
    id: myStack
    anchors.fill: parent

    Test1 
    Test2 
  

Test1.qml

import QtQuick 2.15
import QtQuick.Controls 2.12

Item 
  width: 400
  height: 400

  Button 
    text: "Move Test2"
    onClicked: 
       myStack.currentIndex = 1 // Move to page 2
    
  

Test2.qml

import QtQuick 2.15
import QtQuick.Controls 2.5

Item 
  width: 400 
  height: 400

  Button 
    text: "Move Test1"
    onClicked: 
       myStack.currentIndex = 0 // Move to page 1
    
  

当我拥有如上图所示的结构时,此代码对我有用。我希望这有点帮助。

【讨论】:

以上是关于从另一个 QML 文件打开新的 QML 文件的主要内容,如果未能解决你的问题,请参考以下文章

如何从另一个 QML 文件调用 QML 文件中定义的 Javascript 函数?

如何在 Cascades、Blackberry 10 中使用 Qt/QML/C++ 从另一个 qml 文件中更改一个 qml 文件中的标签文本?

QML , 如何从另一个 qml 访问元素

如何从另一个 QML 访问和控制 ListModel 的内容

为啥我在尝试创建新的 qml 文件时得到 QmlCachedGenerateCode?

如何将 qml 文件重新加载到 QQuickView