在使用QtQuick控件的QtQuick 2中,您可以创建复杂的桌面应用程序。但是在我看来,必须在应用程序启动时声明整个UI并立即创建所有UI。您仍不想创建任何您不想使用的部件(例如“文件”->“打开”对话框),但它们是隐藏的,如下所示:
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解决此问题的信息,但是如您所见,这不是一个很好的解决方案。
好的,为了向您展示为什么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组件就像从C ++动态创建小部件一样丑陋(如果不是那么少,因为它实际上更灵活)。没什么丑陋的事情,您可以在单独的文件中实现QML组件,使用Creator创建的每种帮助,并在需要时根据需要实例化这些组件。从一开始就隐藏所有东西,这很丑陋,而且也很繁重,而且它无法预期动态组件实例化可以发生的所有事情。
这是一个简单的独立示例,它甚至不使用加载程序,因为对话框是本地可用的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 stock之后可用)StackView
。
本文收集自互联网,转载请注明来源。
如有侵权,请联系[email protected] 删除。
我来说两句