Qt 5 QML应用程序,包含许多Windows或复杂的UI

在使用QtQuick控件的QtQuick 2中,您可以创建复杂的桌面应用程序.然而,在我看来,必须在应用程序开始时声明整个UI并立即创建所有UI.您仍然不想使用任何您不想使用的部分(例如File- Open对话框),但它们是隐藏的,如下所示: ApplicationWindow { FileDialog { id:

在使用QtQuick控件的QtQuick 2中,您可以创建复杂的桌面应用程序.然而,在我看来,必须在应用程序开始时声明整个UI并立即创建所有UI.您仍然不想使用任何您不想使用的部分(例如File-> Open对话框),但它们是隐藏的,如下所示:

ApplicationWindow {

  FileDialog {
    id: fileOpenDialog
    visible: false
    // ...
  }
  FileDialog {
    id: fileSaveDialog
    visible: false
    // ...
  }
  // And so on for every window in your app and every piece of UI.

现在,对于简单的应用程序来说这可能没问题,但对于复杂的应用程序或具有许多对话框的应用程序,这肯定是一件疯狂的事情吗?在传统的QtWidgets模型中,您可以在需要时动态创建对话框.

我知道有一些解决方法,例如你可以使用Loader,甚至可以直接在javascript中动态创建QML对象,但是它们非常难看,你会失去优秀的QML语法的所有好处.你也无法真正“卸载”组件. Well Loader声称你可以,但我试过了,我的应用程序崩溃了.

这个问题有优雅的解决方案吗?或者我只需要咬紧牙关并立即为我的应用创建所有潜在的用户界面,然后隐藏其中的大部分内容?

注意:this page提供了有关使用Loaders解决此问题的信息,但正如您所看到的那样,这不是一个非常好的解决方案.

编辑1 – 为什么Loader不是最理想的?

好的,为了向您展示为什么Loader不是那么令人愉快,请考虑这个启动一些复杂任务并等待结果的示例.假设 – 与人们通常给出的所有琐碎的例子不同 – 任务有很多输入和几个输出.

这是Loader解决方案:

Window {
    Loader {
        id: task
        source: "ComplexTask.qml"
        active: false
    }
    TextField {
        id: input1
    }
    TextField {
        id: output1
    }
    Button {
        text: "Begin complex task"
        onClicked: {
                // Show the task.
                if (task.active === false)
                {
                    task.active = true;
                    // Connect completed signal if it hasn't been already.
                    task.item.taskCompleted.connect(onTaskCompleted)
                }

                view.item.input1 = input1.text;
                // And several more lines of that...
            }
        }
    }

    function onTaskCompleted()
    {
        output1.text = view.item.output1
        // And several more lines...

        // This actually causes a crash in my code:
//      view.active = false;
    }
}

如果我在没有Loader的情况下这样做,我可能会有这样的事情:

Window {
    ComplexTask {
        id: task
        taskInput1: input1.text
        componentLoaded: false
        onCompleted: componentLoaded = false
    }

    TextField {
        id: input1
    }
    TextField {
        id: output1
        text: task.taskOutput1
    }

    Button {
        text: "Begin complex task"
        onClicked: task.componentLoaded = true
    }
}

这显然更简单.我明确想要的是加载ComplexTask的一些方法,并在componentLoaded设置为true时激活所有声明关系,然后断开关系并在componentLoaded设置为false时卸载组件.我很确定目前在Qt中没有办法制作这样的东西.

动态地从JS创建QML组件与动态创建小部件一样丑陋(如果不是这样,实际上更灵活).没有什么可丑的,你可以在单独的文件中实现你的QML组件,使用Creator在创建时提供的每个帮助,并在你需要的地方尽可能多地实例化那些组件.让一切都隐藏起来是非常丑陋的,它也更加沉重,它无法预测动态组件实例化可能发生的所有事情.

这是一个简约的自包含示例,它甚至不使用加载器,因为该对话框是本地可用的QML文件.

Dialog.qml

Rectangle {
    id: dialog
    anchors.fill: parent
    color: "lightblue"

    property var target : null

    Column {
        TextField {
            id: name
            text: "new name"
        }
        Button {
            text: "OK"
            onClicked: {
                if (target) target.text = name.text
                dialog.destroy()
            }
        }
        Button {
            text: "Cancel"
            onClicked: dialog.destroy()
        }
    }
}

main.qml

ApplicationWindow {
    visible: true
    width: 200
    height: 200

    Button {
        id: button
        text: "rename me"
        width: 200
        onClicked: {
            var component = Qt.createComponent("Dialog.qml")
            var obj = component.createObject(overlay)
            obj.target = button
        }
    }

    Item {
        id: overlay
        anchors.fill: parent
    }
}

此外,上面的例子是非常准确的,只是为了说明,考虑使用堆栈视图,您自己的实现或自5.1库存StackView后可用.

作者: dawei

【声明】:永州站长网内容转载自互联网,其相关言论仅代表作者个人观点绝非权威,不代表本站立场。如您发现内容存在版权问题,请提交相关链接至邮箱:bqsm@foxmail.com,我们将及时予以处理。

为您推荐

联系我们

联系我们

0577-28828765

在线咨询: QQ交谈

邮箱: xwei067@foxmail.com

工作时间:周一至周五,9:00-17:30,节假日休息

返回顶部