15

All my dialogs appear on the top left corner of screen instead of the center.

What is the best way to let the dialogs be placed automatically correct?

enter image description here

import QtQuick 2.7
import QtQuick.Controls 2.2

ApplicationWindow {
    id: mainWindow

    visible: true
    width: 640
    height: 480
    title: qsTr("Hello World")

    Component.onCompleted: {
        showMessageBox('Hey this actually works!');
    }

    function showMessageBox(message) {
        var component = Qt.createComponent("MessageDialog.qml")
        if(component.status == Component.Ready) {
            var dialog = component.createObject(mainWindow)

            dialog.title = qsTr("Information")
            dialog.text = message

            dialog.open()
        } else
            console.error(component.errorString())
    }
}

With a very simple MessageDialog.qml:

import QtQuick 2.7
import QtQuick.Controls 2.2

Dialog {
    standardButtons: DialogButtonBox.Ok

    property alias text : textContainer.text

    Text {
        id: textContainer

        anchors.fill: parent

        horizontalAlignment: Qt.AlignLeft
        verticalAlignment: Qt.AlignTop
    }
}
eyllanesc
  • 235,170
  • 19
  • 170
  • 241
feedc0de
  • 3,646
  • 8
  • 30
  • 55

5 Answers5

17

The documentation hints, that the Dialog is a descendent of Popup which has x/y-coordinates.

I think those would be a good start to position it.

To your avail:

  • parent.width - which should be the width of your window
  • width - which should be your Dialogs width
  • parent.height
  • height

Calculate the right positions, and you should be fine.

With this you can create a new base class CenteredDialog.qml

Dialog {
    x: (parent.width - width) / 2
    y: (parent.height - height) / 2
}

and then use CenteredDialog instead of Dialog all the time.

Further, for dynamic instantiation you might declare the Component in the file, and only set the properties upon instantiation using the component.createObject(parentObject, { property1Name : property1Value, property2Name : property2Value ... }) syntax.

6

As of Qt 5.12 you can use anchors.centerIn attached property.

Dialog {
    anchors.centerIn: parent
    // ...
}

Then it will be centered on its parent. If you want it to be centered on its window, just set its parent to Overlay.overlay.

lateus
  • 371
  • 4
  • 15
  • 1
    The Qt version detail here was super useful, as I'm trying to support a legacy Qt 5.11 build, which was throwing an error on my attempt to use this "new" feature. – BuvinJ Jan 03 '22 at 22:27
5

You can set x/y position (like derM said), but you have to recalculate every size change of ApplicationWindow!

Here is another solution:

ApplicationWindow {
    id: mainWindow

    visible: true
    width: 640
    height: 480
    title: qsTr("Hello World")

    Component.onCompleted: {
        showMessageBox('Hey this actually works!');
    }

    Item {
        anchors.centerIn: parent
        width: msgDialog.width
        height: msgDialog.height
        MessageDialog {
            id: msgDialog
            title: qsTr("Information")
            visible: false
        }
    }

    function showMessageBox(message) {
        msgDialog.text = message
        msgDialog.visible = true
    }

UPDATE: with dynamic instantiation:

 Item {
    id: dialogParent
    anchors.centerIn: parent
 }

 function showMessageBox(message) {
    var component = Qt.createComponent("MessageDialog.qml")
    if(component.status === Component.Ready) {
        var dialog = component.createObject(dialogParent)

        dialog.title = qsTr("Information")
        dialog.text = message
        dialog.open()

        dialogParent.width = dialog.width
        dialogParent.height = dialog.height
    } else {
        console.error(component.errorString())
    }
 }
Hubi
  • 1,629
  • 15
  • 20
  • Is there any disadvantage when I use `component.createObject`? I just wanted to avoid instantiating all my dialogs when I dont use them (yet). – feedc0de Jul 12 '17 at 08:29
  • No, but you have to change the size of the item with every instantiation. (I added this solution to my answer) – Hubi Jul 12 '17 at 08:38
  • And you need to reparent and reposition the `Item` everytime... Otherwise your `Dialog` won't be in the top layer. Ideally the parent of the `Dialog` is [`ApplicationWindow.overlay`](https://doc.qt.io/qt-5/qml-qtquick-controls2-applicationwindow.html#attached-properties). You could, ofc create one Item in the `ApplicationWindow.overlay`-layer, and reuse this all the time, but then you are limited to one `Dialog` at a time. When you open another one, with a different size, close it thereafter, the right size won't be restored. – derM - not here for BOT dreams Jul 12 '17 at 08:41
  • The dialog will be in a separate qml file and therefore the parent of `dialogParent` won't be the main window. I then tried setting `anchors.centerIn: ApplicationWindow.overlay` but this results in a error message: `Cannot anchor to an item that isn't a parent or sibling.` – feedc0de Jul 17 '17 at 07:57
5

For a generic code which works anywhere, including out of Window/ApplicationWindow, you should use Overlay parent :

Dialog {
    parent: Overlay.overlay // <------- global Overlay object
    readonly property int margin: 16
    width: parent ? (parent.width / 2 - margin) : 128
    height: content.height + margin
    x: parent ? ((parent.width - width) / 2) : 0
    y: parent ? ((parent.height - height) / 2) : 0
    modal: true

   Label {
      id: content
      ...   
   }
}
DevMultiTech
  • 353
  • 3
  • 15
0

anchors.centerIn: Overlay.overlay

Ismet Meta
  • 11
  • 2