arennuit
arennuit

Reputation: 927

QML / Qt Quick weird layout

I am using QML (Qt Quick) in order to set-up the GUI of an app and I am having weird behaviors.

Here is my initial piece of code:

import QtQuick 2.7
import QtQuick.Controls 2.0
import QtQuick.Layouts 1.3

Rectangle {
    id: rectangle1
    color: palette.grey

    ColumnLayout
    {
        id: columnLayout1

        Label
        {
            id: label1
            text: qsTr("Target")
            font.pointSize: 22
        }

        ProgressBar
        {
            id: progressBar1
            value: 0.5
        }
    } }

... which gives layout:

Initial layout

Then I anchor the centers:

import QtQuick 2.7
import QtQuick.Controls 2.0
import QtQuick.Layouts 1.3

Rectangle
{
    id: rectangle1
    color: palette.grey

    ColumnLayout
    {
        id: columnLayout1
        anchors.horizontalCenter: parent.horizontalCenter
        anchors.verticalCenter: parent.verticalCenter

        Label
        {
            id: label1
            text: qsTr("Target")
            font.pointSize: 22
        }

        ProgressBar
        {
            id: progressBar1
            value: 0.5
        }
    }
}

No problem here, I get:

enter image description here

Now things go wrong when I rotate the slider:

import QtQuick 2.7
import QtQuick.Controls 2.0
import QtQuick.Layouts 1.3

Rectangle
{
    id: rectangle1
    color: palette.grey

    ColumnLayout
    {
        id: columnLayout1
        anchors.horizontalCenter: parent.horizontalCenter
        anchors.verticalCenter: parent.verticalCenter

        Label
        {
            id: label1
            text: qsTr("Target")
            font.pointSize: 22
        }

        ProgressBar
        {
            id: progressBar1
            rotation: 90
            value: 0.5
        }
    }
}

And here I was expecting Qt to rotate the slider and use the rotated slider to compute the layout, but it is not what happens. Actually the layout seems to be computed with the slider unrotated then only the slider is rotated. This ends up with a layout which is no longer a column:

enter image description here

This looks a bit buggy, no? Or am I doing something wrong?

Now another problem occurs when I wrap the slider in an Item (I was actually playing with Items to see if I could find a workaround):

import QtQuick 2.7
import QtQuick.Controls 2.0
import QtQuick.Layouts 1.3

Rectangle
{
    id: rectangle1
    color: palette.grey

    ColumnLayout
    {
        id: columnLayout1
        anchors.horizontalCenter: parent.horizontalCenter
        anchors.verticalCenter: parent.verticalCenter

        Label
        {
            id: label1
            text: qsTr("Target")
            font.pointSize: 22
        }

        Item
        {
            ProgressBar
            {
                id: progressBar1
                value: 0.5
            }
        }
    }
}

And in this case what I get is a slider above the label (although it is defined after it in the code):

enter image description here

This also looks weird to me... Anybody has an idea of what I did wrong?

Please note that the screen shots are captured from Designer but running the program leads to the exact same problems.

Kind regards,

Antoine Rennuit.

Upvotes: 1

Views: 462

Answers (1)

Mitch
Mitch

Reputation: 24386

Now things go wrong when I rotate the slider

Rotation doesn't affect the width or height properties. You can check this by adding the following lines to your ProgressBar:

onWidthChanged: print("width", width)
onHeightChanged: print("height", height)

If ProgressBar had an orientation property, like it does in Qt Quick Controls 1, you could use that instead of rotation. You can't simply flip the width and height when rotating the bar, either, because layouts use the implicitWidth and implicitHeight, not width and height:

import QtQuick 2.7
import QtQuick.Controls 2.0
import QtQuick.Layouts 1.3

import QtQuick.Controls 2.1

ApplicationWindow {
    width: 400
    height: 300
    visible: true

    ColumnLayout {
        id: columnLayout1
        anchors.horizontalCenter: parent.horizontalCenter
        anchors.verticalCenter: parent.verticalCenter

        Label {
            id: label1
            text: qsTr("Target")
            font.pointSize: 22
        }

        ProgressBar {
            id: progressBar1
            rotation: 90
            width: implicitHeight
            height: implicitWidth
            value: 0.5
        }
    }
}

You could calculate the implicitWidth and implicitHeight yourself, but that's not nice.

Now another problem occurs when I wrap the slider in an Item

You're on the right track here. As mentioned in this answer, you need to give the Item a size. You can do so like this:

import QtQuick 2.7
import QtQuick.Controls 2.0
import QtQuick.Layouts 1.3

import QtQuick.Controls 2.1

ApplicationWindow {
    width: 400
    height: 300
    visible: true

    ColumnLayout {
        id: columnLayout1
        anchors.horizontalCenter: parent.horizontalCenter
        anchors.verticalCenter: parent.verticalCenter

        Label {
            id: label1
            text: qsTr("Target")
            font.pointSize: 22
        }

        Item {
            implicitWidth: progressBar1.implicitHeight
            implicitHeight: progressBar1.implicitWidth

            ProgressBar {
                id: progressBar1
                rotation: 90
                value: 0.5
            }
        }
    }
}

Notice that the progress bar still isn't in the correct position. That's because the default transform origin for items is in the centre. Setting it to the BottomLeft works:

import QtQuick 2.7
import QtQuick.Controls 2.0
import QtQuick.Layouts 1.3

import QtQuick.Controls 2.1

ApplicationWindow {
    width: 400
    height: 300
    visible: true

    ColumnLayout {
        id: columnLayout1
        anchors.horizontalCenter: parent.horizontalCenter
        anchors.verticalCenter: parent.verticalCenter

        Label {
            id: label1
            text: qsTr("Target")
            font.pointSize: 22
        }

        Item {
            implicitWidth: progressBar1.implicitHeight
            implicitHeight: progressBar1.implicitWidth + progressBar1.implicitHeight

            ProgressBar {
                id: progressBar1
                rotation: 90
                transformOrigin: Item.BottomLeft
                value: 0.5
            }
        }
    }
}

Note that you also have to add the implicitHeight of the bar to the implicitHeight of the Item, in order to account for the transform origin change we did.

I'd strongly recommend you create a suggestion for an orientation property on bugreports.qt.io. :)

Upvotes: 2

Related Questions