user3417815
user3417815

Reputation: 635

QtQuick 2 - Custom element, how to resize root object ot it's content?

Is there a way to resize custom element to fit it's content? I wrote some button example on QML, but I need that to resize with text length each time scene played if size not defined in main.qml. Sorry, but can't find something about that over network, only reverse question on how to fit content to parent. There is a source:

BreezeButton.qml

import QtQuick 2.2
Item {
    id: root
    width: 172
    height: 72
    property string caption: "Button"
    property string iconSource: null
    signal clicked
    Rectangle {
        id: body
        border {
            width: 2
            color: "#808e8e"
        }
        anchors{
            fill: parent
        }
        gradient: Gradient {
            id: bodyGradient
            GradientStop { position: 0.4; color: "#4d4d4d" }
            GradientStop { position: 0.9; color: "#31363b" }
        }
        MouseArea{
            id: bodyMouseArea
            z: bodyText.z + 1
            anchors {
                fill: parent
            }

            hoverEnabled: true
            onEntered: {
                body.border.color = "#3daee9"

            }
            onExited: {
                body.border.color = "#7f8c8d"
            }
            onPressed: {
                body.color = "#3daee9"
                body.gradient = null
            }
            onReleased: {
                body.color = "#4d4d4d"
                body.gradient = bodyGradient
            }
            onClicked: {
                root.clicked()
            }
        }
        Text {
            id: bodyText
            anchors {
                top: body.top
                bottom: body.bottom
                left: icon.right
            }
            width: body.width - icon.width
            font.pointSize: 14
            color: "#fcfcfc"
            text: caption
            verticalAlignment: Text.AlignVCenter
            horizontalAlignment: Text.AlignHCenter
        }
        Image {
            id: icon
            source: iconSource
            anchors {
                left: body.left
                top: body.top
                bottom: body.bottom
                leftMargin: 5
                topMargin: 5
                bottomMargin: 5
            }
            height: root.height - 8
            width: icon.height
            sourceSize.width: icon.width
            sourceSize.height: icon.height
        }
    }
}

For example basic QML Button can resize each time scene played to fit it's text length.

Upvotes: 0

Views: 1650

Answers (1)

Mitch
Mitch

Reputation: 24386

It's good to take advantage of the fact that Qt is open source. Almost everything you need to know about how to achieve something that Qt does can be found by getting your hands dirty in the codebase. You mentioned Qt Quick Controls' Button type, so it would help to look there.

Searching through Button.qml only gives results for menu width and height, which is not useful for us.

Let's look at its base type: BasicButton. No mention of width or height there, either.

If you are familiar with Qt Quick Controls, you'll remember that the controls usually have an associated style, and the components in these styles often determine the size of the control, which is very similar to what you want to achieve.

But let's assume you're not familiar with that, because it's still possible to find out what you want to know, you just need to have more patience. So, now would be a good time to go to your console and run git grep Button in qt5/qtquickcontrols. If you do that, you'll get a lot of results. I'm not going to go through all of them, because that's the point of this exercise: to sharpen your ability to find what you're looking for. A lot of the results that you'll see are not directly related to Button, however.

Let's also assume that you went through the results and spotted the ButtonStyle.qml matches. These are the only results that sound interesting to us, so open that file. Looking at the components, we see background and label. Notice that they're both specifying implicitWidth and implicitHeight... interesting. Read the documentation for these:

Defines the natural width or height of the Item if no width or height is specified.

...

Setting the implicit size is useful for defining components that have a preferred size based on their content, for example:

// Label.qml
import QtQuick 2.0

Item {
    property alias icon: image.source
    property alias label: text.text
    implicitWidth: text.implicitWidth + image.implicitWidth
    implicitHeight: Math.max(text.implicitHeight, image.implicitHeight)
    Image { id: image }
    Text {
        id: text
        wrapMode: Text.Wrap
        anchors.left: image.right; anchors.right: parent.right
        anchors.verticalCenter: parent.verticalCenter
    }
}

We've already got a pretty good idea of what to do now, but let's confirm it by seeing how Button's components are used:

/*! \internal */
property Component panel: Item {
    anchors.fill: parent
    implicitWidth: Math.max(labelLoader.implicitWidth + padding.left + padding.right, backgroundLoader.implicitWidth)
    implicitHeight: Math.max(labelLoader.implicitHeight + padding.top + padding.bottom, backgroundLoader.implicitHeight)
    baselineOffset: labelLoader.item ? padding.top + labelLoader.item.baselineOffset : 0

    Loader {
        id: backgroundLoader
        anchors.fill: parent
        sourceComponent: background
    }

    Loader {
        id: labelLoader
        sourceComponent: label
        anchors.fill: parent
        anchors.leftMargin: padding.left
        anchors.topMargin: padding.top
        anchors.rightMargin: padding.right
        anchors.bottomMargin: padding.bottom
    }
}

The recurring theme here is implicitWidth and implicitHeight, and we were able to deduce that by looking at the code. Of course it takes longer to do if you're not familiar with the code, but the more you do it, the easier it becomes, especially in the context of a specific framework.

Upvotes: 4

Related Questions