gpt4 book ai didi

qt - 如何更改 QML 对话框/窗口的 transient 父级?

转载 作者:行者123 更新时间:2023-12-02 03:25:29 44 4
gpt4 key购买 nike

我正在开发一个 Qt (5.3) 桌面应用程序(带有 QML ui 的 C++ 核心),其主窗口是一个 ApplicationWindow 并且在某个时候启动 Dialog s。由于 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 的 transient 父级。

我找到了解决此问题的方法,方法是在发生这种情况时手动将对话框置于前面:

MainWindow {
// ...
onActiveChanged: {
if (Qt.platform.os === "windows") {
if (active) {
// ...
if (aboutDialog.visible) {
aboutDialog.requestActivate()
}
// ...
}
}
}
// ...
}

但我认为,如果可能的话,最好避免这种解决方法。在深入研究 Qt 文档但没有任何运气后,我决定发布这个问题,可以按如下方式恢复:是否可以更改 QML 窗口的 transient 父窗口?如果是这样,请您指出如何实现?

欢迎提出有关可以避免重复内容的不同方法的建议。

最佳答案

我想这是不可能的。至少在 Qt 5.4 中是这样。

来自文档(QML 类型“Window”的默认属性“data”)

data : list The data property allows you to freely mix visual children, resources and other Windows in a Window.

If you assign another Window to the data list, the nested window will become "transient for" the outer Window.

If you assign an Item to the data list, it becomes a child of the Window's contentItem, so that it appears inside the window. The item's parent will be the window's contentItem, which is the root of the Item ownership tree within that Window.

If you assign any other object type, it is added as a resource.

It should not generally be necessary to refer to the data property, as it is the default

property for Window and thus all child items are automatically assigned to this property.

由于 QML 绑定(bind)限制,“窗口”的所有动态创建似乎都有错误的 transient 父级。所有 QML 列表元素均不可修改。因此,不建议使用具有属性绑定(bind)的列表。如果它发生变化,您将永远不会收到通知信号。因此,我猜想,QML 引擎永远不知道新的 QML 元素是“Window”类型,并且有必要将其添加到 Windows 层次结构中。

来自文档 (https://www.ics.com/files/qtdocs/qml-list.html):

A list property cannot be modified in any other way. Items cannot be dynamically added to or removed from the list through JavaScript operations; any push() operations on the list only modify a copy of the list and not the actual list. (These current limitations are due to restrictions on Property Binding where lists are involved.)

也许这是一个错误,也许是一个功能。无论如何,目前不可能使用适当的 transient 父级动态加载“窗口”类型。

我发现的最佳解决方法 - 使用modality: Qt.ApplicationModal作为对话框。

关于qt - 如何更改 QML 对话框/窗口的 transient 父级?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23730153/

44 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com