在使用 QtQuick 控件的 QtQuick 2 中,您可以创建复杂的桌面应用程序。但是在我看来,整个 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 语法的所有好处。您也不能真正“卸载”组件。好吧Loader
,你可以,但我试过了,我的应用程序崩溃了。
这个问题有优雅的解决方案吗?还是我只需要咬紧牙关,一次为我的应用创建所有潜在的 UI,然后隐藏大部分?
注意:这个页面有关于使用Loader
s 来解决这个问题的信息,但是你可以看到它不是一个很好的解决方案。
编辑 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 中制作这样的东西。