我正在开发一个Qt(5.3)桌面应用程序(带有QML ui的C++核心),其主窗口是一个ApplicationWindow,并且在某些时候启动Dialogs.由于在Windows和Mac OS X之间使用对话框模式存在差异(例如,关于对话框在Mac OS X上很少是模态的,但在Windows上几乎总是模态的),而且在呈现一些对话框的内容方面,我也是我们改变了设计,允许实现特定于平台的对话框版本.
为此我创建了以下DialogLoader:
Loader {
id: dialogFactory
property string dialogName
function platformFolder() {
if (Qt.platform.os === "osx")
return "osx"
return "win"
}
onDialogNameChanged: { source = platformFolder() + "/" + dialogName + ".qml" }
onStatusChanged: {
if (dialogFactory.status === Loader.Error)
console.log("DialogFactory: failed to load file: " + source);
else if (dialogFactory.status === Loader.Ready)
console.log("DialogFactory: file \"" + source + "\" loaded")
}
}
Run Code Online (Sandbox Code Playgroud)
我用的如下:
ApplicationWindow {
// …
property alias aboutDialog: aboutDialogLoader.item
// …
DialogLoader { id: aboutDialogLoader; dialogName: "AboutDialog" }
// …
Action { text: qsTr("About..."); onTriggered: aboutDialog.show() }
// …
}
Run Code Online (Sandbox Code Playgroud)
这种方法工作正常,它符合我的需要,除了一件事:Windows上的模态对话框的行为与我ApplicationWindow直接声明它们时的行为不同.如果应用程序在打开模态窗口并且再次授予焦点时失去焦点,则模式窗口将出现在主窗口后面,这会导致应用程序无法运行.
经过一些研究后,我意识到问题的原因在于,使用加载器方法ApplicationWindow并不是作为瞬态父级的Dialog.
我已经找到了一个解决方法,通过在发生这种情况时手动将Dialog置于前面:
MainWindow {
// ...
onActiveChanged: {
if (Qt.platform.os === "windows") {
if (active) {
// ...
if (aboutDialog.visible) {
aboutDialog.requestActivate()
}
// ...
}
}
}
// ...
}
Run Code Online (Sandbox Code Playgroud)
但我认为如果可能的话,最好避免这种解决方法.在没有任何运气的情况下深入研究Qt文档之后,我决定发布这个问题,可以恢复如下:是否可以更改QML窗口的瞬态父级?如果是这样,请你指出如何?
我们欢迎有关避免重复使用的不同方法的建议.
我想这是不可能的。至少在 Qt 5.4 中是这样。
来自文档(QML 类型“Window”的默认属性“data”)
data : list data 属性允许您在一个 Window 中自由混合可视子项、资源和其他 Windows。
如果将另一个窗口分配给数据列表,则嵌套窗口将成为外部窗口的“瞬态”。
如果将一个 Item 分配给数据列表,它将成为 Window 的 contentItem 的子项,以便它出现在窗口内。该项目的父级将是窗口的 contentItem,它是该窗口内项目所有权树的根。
如果您分配任何其他对象类型,它将作为资源添加。
通常不需要引用 data 属性,因为它是默认值
Window 的属性,因此所有子项都会自动分配给该属性。
由于 QML 绑定限制,似乎所有“窗口”的动态创建都有错误的瞬态父级。所有 QML 列表元素均不可修改。因此,不建议使用具有属性绑定的列表。如果它发生变化,您将永远不会收到通知信号。因此,我猜想,QML 引擎永远不知道新的 QML 元素是“Window”类型,并且有必要将其添加到 Windows 层次结构中。
来自文档(https://www.ics.com/files/qtdocs/qml-list.html):
不能以任何其他方式修改列表属性。无法通过 JavaScript 操作动态地将项目添加到列表或从列表中删除;列表上的任何 push() 操作都只会修改列表的副本,而不是实际的列表。(这些当前限制是由于涉及列表的属性绑定的限制造成的。)
也许这是一个错误,也许是一个功能。无论如何,目前不可能使用适当的瞬态父级动态加载“窗口”类型。
我发现的最好的解决方法 - 使用模态:Qt.ApplicationModal进行对话框。
| 归档时间: |
|
| 查看次数: |
1764 次 |
| 最近记录: |