【问题标题】:Implement functionality of multiple windows in same file?在同一个文件中实现多个窗口的功能?
【发布时间】:2015-01-09 15:21:23
【问题描述】:

在我的 Qt Quick(Qt v5.4 和 QtQuick 2.4)项目中,我有这五个 .qml 文件:

  1. MainForm.ui.qml - 包含应用程序的主窗口
  2. main.qml - 包含 mainForm.ui.qml 对象的所有功能实现,例如 onClicked 事件、调用 c++ 函数从 textInputs 获取值等。

问:我当前用于实现功能的设置是否正确?还是应该在同一个文件中实现所有这些东西?

  1. dialog1.qml - 包含用于某些设置等的一些文本输入。
  2. dialog2.qml - 我的应用程序中的一些列表和表格。
  3. dialog3.qml - 还包含一些用于 c++ 函数的对象。

所有这些 qml 文件都是在不同时间、不同按钮单击时创建和销毁的。我正在使用这种方法打开一个对话框

`addMenuArea.onClicked: {
Qt.createComponent("addMenuAppDialog.qml").createObject(rootWindow, {});
}`

以及销毁对话框:

MouseArea{
    anchors.fill: parent
    onClicked: {
        dialogComponent.destroy()
    }
}

现在这些对话框没有任何功能,比如主窗口,如果可能的话,我想在一个文件(main.qml)中实现所有功能,而不需要任何 javascript。我不知道如何链接所有对话框和 main.qml,所以我可以在 main.qml 中添加函数。任何帮助都会很棒!

【问题讨论】:

  • 哪个 qt 和哪个 qt-quick?缺少版本信息。
  • @user1095108 编辑问题,看看!
  • 这是一种可能的方式。另一种方法是使用Loader 并更改源文件名。这将处理对象的创建/销毁。第三种方法是实例化所有对话框并隐藏所有对话框,除了应该可见的对话框,但这会占用比需要更多的内存。
  • @saiarcot895 我正在为此搜索文档。 Loader 中是否有一些方法或函数可以链接对话框和 main.qml??
  • @EdwardMckinzie:Loader.item 包含对被加载的顶级对象的引用。您可以将其与Loader.source 结合使用。

标签: c++ qt qml qt-quick


【解决方案1】:

假设您有一个SimpleDialog.qml 文件:

Window { //or Item, Rectangle, ... whatever
    signal userPressedSomething()
    property string userNameString
    function textEditText(){ /*return textEdit.text()*/ }
    //...
}

并假设您的main.qml 具有以下功能来尝试处理必要的程序逻辑:

  1. openSimpleDialog() 加载 SimpleDialog
  2. closeSimpleDialog() 关闭SimpleDialog
  3. userPressedSomethingInSimpleDialog()
  4. getSimpleDialogInfo()

您可以使用Loader 加载、卸载、从对话框中获取数据,并使用Connections 捕获信号。这是main.qml中的一个简单示例:

Loader { id: simpleDialogLoader }

function openSimpleDialog() { simpleDialogLoader.source = "SimpleDialog.qml"; }

function closeSimpleDialog() { simpleDialogLoader.source = ""; }

function getSimpleDialogInfo() {
    if (simpleDialogLoader.source !== "SimpleDialog.qml") { return; }
    console.log(simpleDialogLoader.item.userNameString); //property
    console.log(simpleDialogLoader.item.textEditText()); //function
}

Connections {
    target: simpleDialogLoader //to Loader
    onUserPressedSomething: { userPressedSomethingInSimpleDialog(); }
}

让我们解释一下细节:

  • 使用Loader.source 属性在openSimpleDialogcloseSimpleDialog 函数中动态加载/卸载SimpleDialog
  • Loader.item 持有加载器创建的对象,这就是getSimpleDialogInfo 需要的全部。
  • 来自SimpleDialogcan be caught 的信号通过将Connections.target 设置为Loader.item。

【讨论】:

  • 谢谢!如果我想在 simpleDialog.qml 中的按钮时实现一个更改某些文本或某种颜色的函数,正如我所说的我想在 main.qml 中实现?我还想知道如何添加当 simpleDialog.qml 中的按钮被按下时我得到滑块或textEdit 的值?我想将这些值用作 C++ 函数中的参数吗?
  • 如果您想在用户按下 main.qml 中的某些内容时更改 SimpleDialog.qml 中的某些文本,请尝试 getSimpleDialogInfo 方法。另一方面,如果您想在用户按下 SimpleDialog.qml 中的某些内容时更改 main.qml 中的某些文本,请尝试 Connections 方法(SimpleDialog 应该显式发出信号)。在这两种情况下都不需要 C++。
【解决方案2】:

虽然您可以在main.qml 文件中定义所有对话框和主窗口,但我强烈反对这种方法。随着您的对话框和主窗口变得越来越复杂(它们肯定会变得更加复杂),您的 QML 代码将变得越来越难以理解。

在做

Qt.createComponent("addMenuAppDialog.qml").createObject(rootWindow, {})

涉及从 HDD 加载 QML 文件,因此我不建议在每次鼠标单击时调用它。我建议了 2 种替代该方法的方法。

备选方案 1

为主窗口中的每个对话框创建一个组件:

Component {
    id: dialog1Component
    Dialog1 {}
}

然后你就可以通过调用dialog1Component.createObject(rootWindow, {})来创建它,当它关闭时你仍然需要手动destroy它。

备选方案 2

这是在我的应用中用于呈现对话框的方法。

以声明方式创建对话框(将其放在主窗口中):

MainWindow {
    Dialog1 {
        id: dialog1
    }
}

然后您可以通过调用dialog1.open() 来显示它并通过调用dialog1.close() 来隐藏它。

【讨论】:

  • 谢谢!在备选方案 2 中,是否可以使用自己的自定义样式添加自定义 QML 组件,如 ListView 或 TextInputs,或使用其他 qml 文件作为组件??
  • @EdwardMckinzie 是的,你绝对可以做类似 `MainWindow { Dialog1 { TextInput { /* blah blah blah */ } }
猜你喜欢
  • 2019-09-06
  • 2021-10-22
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-12-10
  • 2018-05-10
  • 1970-01-01
相关资源
最近更新 更多