显示对话框 onCompleted 无法按预期工作
Posted
技术标签:
【中文标题】显示对话框 onCompleted 无法按预期工作【英文标题】:Showing a Dialog onCompleted doesn't work as expected 【发布时间】:2015-09-13 18:28:25 【问题描述】:我想在某些条件下显示Dialog
onCompleted
(此处省略处理此条件 - 一个简单的if
子句)
main.qml
:
import QtQuick 2.2
import QtQuick.Controls 1.0
ApplicationWindow
id: appWindow
width: 480
height: 640
visible: true
StackView
id: stackView
anchors.fill: parent
// Implements back key navigation
focus: true
initialItem: Item
width: parent.width
height: parent.height
Button onClicked: dialog.open()
// ...
Component.onCompleted: dialog.open()
MyDialog id: dialog
MyDialog.qml
import QtQuick 2.0
import QtQuick.Dialogs 1.2
import QtQuick.Layouts 1.0
import QtQuick.Controls 1.0
Dialog
id: root
title: "MyDialog"
standardButtons: Qt.NoButton
ColumnLayout
id: column
width: parent ? parent.width : 200
Label text: "hello world"; Layout.fillWidth: true
当我启动我的应用程序时,屏幕变暗,Dialog
的阴影出现,好像对话框有width == 0
。
有时(很少)对话框会正确显示。
如果我注释掉Component.onCompleted
行并使用Button
启动对话框,它会正确显示。
我做错了什么? 我正在使用适用于 android 的 Qt 5.5
【问题讨论】:
【参考方案1】:如果在窗口具有健全的几何形状之前打开对话框,则无法正常打开对话框。
一个安全的选择是使用onWidthChanged
信号
main.qml
import QtQuick 2.2
import QtQuick.Controls 1.0
ApplicationWindow
id: appWindow
width: 480
height: 640
visible: true
StackView
id: stackView
anchors.fill: parent
// Implements back key navigation
focus: true
initialItem: Item
property bool firstTime: true
width: parent.width
height: parent.height
// ...
// width may be called multiple times
onWidthChanged: if (firstTime) firstTime = true; dialog.open()
MyDialog id: dialog
【讨论】:
【参考方案2】:请参考Dialog QML Type的官方文档,在那里你可以找到下一个:
注意:不要尝试将对话框的宽度或高度绑定到 其内容的宽度或高度,因为 Dialog 已经尝试调整大小 本身的内容。如果您的目标是改变或消除 边距,您必须覆盖 contentItem。如果你的目标只是展示 一个窗口(无论是否模式),并且您的平台支持它,它是 改用 Window 更简单。
因此,在您的情况下,最好以某种方式隐式设置内部元素的宽度。另一种快速的解决方案是添加(例如)具有给定宽度的Rectangle
元素作为对话框的一个内部根元素。您可以在此 Rectangle
中放置其他元素。
【讨论】:
只有当我启动对话框onCompleted
时才会出现问题(请参阅更新的 OP)。 Qt 示例本身建议将width
设置为parent.width
,参见doc.qt.io/qt-5/…
首先,你是对的——原始示例中的有趣点。其次,它是 QML -> IMO,永远无法 100% 确定。这是从文档中引用到(组件)[doc.qt.io/qt-5/qml-qtqml-component.html]:>相应的处理程序是onCompleted
。它可以在任何对象上声明。 onCompleted
处理程序的运行顺序是未定义。只是一个测试说明——尝试在 StackedView depth
更改上触发 dialog.open()
。
是的,就是这样。我发布了一个我制定的解决方案。使用Stack.status
附加属性甚至比使用depth
更有效。如果您有更好的想法,请发布。
不,我没有更好的主意。看来你的解决方法没问题。
使用Stack.status
并不总是有效。我刚刚发现了:(【参考方案3】:
我发布另一个答案,因为它是另一种方法。我记得我是如何在一些旧项目上实现它的。 AFAIK,目前这是最好的方法。 如果有人提供更好的解决方案,我会很高兴。
您需要添加一个中间元素,例如Timer
。这个计时器(tm
在下面的代码中)必须有小间隔(比如 30 毫秒)并且需要在你想要的事件上启动——Component.onCompleted
。将您的操作放入此计时器的onTriggered
。
代码如下:
ApplicationWindow
title: qsTr("Hello World")
width: 640
height: 480
visible: true
Timer
id: tm
interval: 30
onTriggered: dialog.open()
StackView
id: stackView
anchors.fill: parent
// Implements back key navigation
focus: true
initialItem: Item
width: parent.width
height: parent.heonTriggeredight
Button onClicked: dialog.open()
Component.onCompleted: tm.start()
MyDialog id: dialog
【讨论】:
以上是关于显示对话框 onCompleted 无法按预期工作的主要内容,如果未能解决你的问题,请参考以下文章