0
votes

I want to show a Dialog onCompleted under some condition (handling this condition omitted here - a simple if clause)

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 }
    }
}

When I launch my app, the screen is dimmed, and the Dialog's shade appears, as though the dialog had width == 0.

Sometimes (rarely) the dialog shows correctly.

If I comment out the Component.onCompleted line and launch the dialog using the Button, it is displayed correctly.

What am I doing wrong? I'm using Qt 5.5 for Android

3

3 Answers

2
votes

Opening the dialog doesn't work correctly if it's opened before the window has a sane geometry.

A safe option is to use the onWidthChanged signal

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 }
}
1
votes

Please, refer to official documentation about Dialog QML Type, there you can find next:

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.

So, in your case, it will be better somehow set width of your inner element implicitly. Another quick solution is to add (for example) Rectangle element with given width as only one inner root element of your Dialog. Rest of elements you can place inside this Rectangle.

1
votes

I'm posting another answer because it is another approach. I remembered how I implemented it on some old project. AFAIK, For now it is the best way. I would be really happy if anyone gave better solution.

You need to add one intermediary element like Timer. This timer (tm in code below) must have small interval (like 30ms) and need to be started on your desired event -- Component.onCompleted. Put your action in onTriggered of this timer.

Here is code:

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 }
}