我正在开发一个Qt(5.3)桌面应用程序(带有QML ui的C ++核心),其主窗口是ApplicationWindow
,并且在某个时刻启动Dialog
。
由于在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")
}
}
我使用如下:
ApplicationWindow {
// …
property alias aboutDialog: aboutDialogLoader.item
// …
DialogLoader { id: aboutDialogLoader; dialogName: "AboutDialog" }
// …
Action { text: qsTr("About..."); onTriggered: aboutDialog.show() }
// …
}
这种方法工作正常,除了一件事,它符合我的需要:
Windows上的模态对话框的行为与我在ApplicationWindow
中直接声明它们时的行为不同。如果在打开模态窗口并且再次授予焦点时应用程序失去焦点,则主窗口后面会出现模态窗口,导致应用程序无法运行。
经过一番研究后,我意识到问题的原因在于,使用加载器方法ApplicationWindow
并不是Dialog
的短暂父项。
我已经找到了解决方法,通过在发生这种情况时手动将Dialog置于前面:
MainWindow {
// ...
onActiveChanged: {
if (Qt.platform.os === "windows") {
if (active) {
// ...
if (aboutDialog.visible) {
aboutDialog.requestActivate()
}
// ...
}
}
}
// ...
}
但我认为如果可能的话,最好避免这种解决方法。在没有任何运气的情况下深入研究Qt文档之后,我决定发布这个问题,可以恢复如下: 是否可以更改QML窗口的瞬态父级?如果是这样,请你指出怎么做?
欢迎提出有关避免重复使用的不同方法的建议。
答案 0 :(得分:3)
我想这是不可能的。至少在Qt 5.4中。
来自文档(默认属性"数据" QML类型" Window")
data:list data属性允许您自由混合视觉 窗口中的子项,资源和其他Windows。
如果您将另一个窗口指定给数据列表,嵌套窗口将会 成为"瞬态的"外窗。
如果您将一个项目分配给数据列表,它将成为该项目的子项 Window的contentItem,以便它出现在窗口内。该项目 parent将是窗口的contentItem,它是Item的根 该窗口内的所有权树。
如果您指定任何其他对象类型,则会将其添加为资源。
通常不需要引用data属性,如 这是默认的
Window的属性,因此所有子项都是自动的 分配给这家酒店。
似乎所有动态创建" Window"由于QML绑定限制,有错误的瞬态父。所有QML列表元素都不可修改。因此,不建议使用具有属性绑定的列表。如果发生变化,您将永远不会收到通知信号。所以,我想,QML引擎永远不会知道新的QML元素是" Window"输入并将其添加到Windows层次结构中。
来自文档(https://www.ics.com/files/qtdocs/qml-list.html):
无法以任何其他方式修改列表属性。物品不能 通过JavaScript动态添加到列表或从列表中删除 操作;列表上的任何push()操作只会修改一个副本 列表而不是实际列表。 (这些当前的限制是应该的 限制涉及列表的属性绑定。)
也许这是一个错误,也许是功能。无论如何,现在无法加载" window"使用适当的瞬态父动态进行动态输入。
我找到的最佳解决方法 - 使用模态:Qt.ApplicationModal 进行对话。