显示对话框 onCompleted 无法按预期工作
Showing a Dialog onCompleted doesn't work as expected
我想在某些条件下显示一个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
请参考关于Dialog QML Type的官方文档,在那里你可以找到下一个:
Note: do not attempt to bind the width or height of the dialog to the
width or height of its content, because Dialog already tries to size
itself to the content. If your goal is to change or eliminate the
margins, you must override contentItem. If your goal is simply to show
a window (whether modal or not), and your platform supports it, it is
simpler to use Window instead.
因此,在您的情况下,以某种方式隐式设置内部元素的宽度会更好。另一种快速解决方案是添加(例如)具有给定宽度的 Rectangle
元素作为对话框的唯一一个内部根元素。您可以将其他元素放入此 Rectangle
.
如果在 window 具有合理的几何形状之前打开对话框,则打开对话框将无法正常工作。
一个安全的选择是使用 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 }
}
我发布了另一个答案,因为这是另一种方法。我记得我是如何在一些旧项目上实施它的。 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 }
}
我想在某些条件下显示一个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请参考关于Dialog QML Type的官方文档,在那里你可以找到下一个:
Note: do not attempt to bind the width or height of the dialog to the width or height of its content, because Dialog already tries to size itself to the content. If your goal is to change or eliminate the margins, you must override contentItem. If your goal is simply to show a window (whether modal or not), and your platform supports it, it is simpler to use Window instead.
因此,在您的情况下,以某种方式隐式设置内部元素的宽度会更好。另一种快速解决方案是添加(例如)具有给定宽度的 Rectangle
元素作为对话框的唯一一个内部根元素。您可以将其他元素放入此 Rectangle
.
如果在 window 具有合理的几何形状之前打开对话框,则打开对话框将无法正常工作。
一个安全的选择是使用 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 }
}
我发布了另一个答案,因为这是另一种方法。我记得我是如何在一些旧项目上实施它的。 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 }
}