显示对话框 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 }
}