Search code examples
qmlqt5qtquick2

Custom Button with conditional image and conditional text


I have the following custom QML Button:

import QtQuick.Controls 1.4
import QtQuick 2.5
import QtQuick.Layouts 1.2
import QtMultimedia 5.5

Rectangle {
    id: ueButton

    property string ueText: ""
    property string ueIconPath: ""

    width: 256
    height: 128

    signal ueSignalButtonClicked

    gradient: Gradient {
        GradientStop {
            position: 0

            color: "#ffffff"

            SequentialAnimation on color {
                id: ueButtonClickAnimation

                loops: 1
                running: false

                ColorAnimation {
                    from: "#ffffff"
                    to: "#000000"
                    duration: 25
                }   // ColourAnimation

                ColorAnimation {
                    from: "#000000"
                    to: "#ffffff"
                    duration: 25
                }   // ColorAnimation
            }   // SequentialAnimation
        }   // GradientStop

        GradientStop {
            position: 0.418

            color: "#000000"
        }   // GradientStop
    }   // Gradient

    border.color: "steelblue"
    border.width: 1
    radius: 4

    antialiasing: true
    smooth: true

    ColumnLayout {
        anchors.fill: parent
        antialiasing: true

        Image {
            Layout.fillWidth: true
            Layout.fillHeight: true
            Layout.alignment: Qt.AlignHCenter|Qt.AlignTop
            Layout.margins: 8

            asynchronous: true

            horizontalAlignment: Image.AlignHCenter
            verticalAlignment: Image.AlignVCenter

            fillMode: Image.PreserveAspectFit

            smooth: true

            source: ueIconPath
        }   // Image

        Text {
            text: ueText

            Layout.fillWidth: true
            Layout.fillHeight: true
            Layout.alignment: Qt.AlignHCenter|Qt.AlignVCenter
            Layout.topMargin: 8
            Layout.leftMargin: 8
            Layout.rightMargin: 8
            Layout.bottomMargin: 16

            color: "#ffffff"
            font.bold: true
            verticalAlignment: Text.AlignVCenter
            horizontalAlignment: Text.AlignHCenter
            font.pointSize: 16
            textFormat: Text.RichText
        }   // Text
    }   // ColumnLayout

    MouseArea {
        id: ueButtonMouseArea
        antialiasing: true

        anchors.fill: parent

        onClicked: {
            ueButtonClickAnimation.running=true
            ueSignalButtonClicked()
        }
    }   // MouseArea
}   // ueButton

This works fine, but what I want to do now is to solve the following two issues:

  1. If urtext is empty, the corresponding text is ignored and the whole ColumnLayout place is reserved for Image.
  2. If ueIconPath is empty, the corresponding image is ignored and the whole ColumnLayout is reserved for Text.

How can I achieve that?


Solution

  • As @BaCaRoZzo already suggested, using styles is preferable solution in this case since the item itself is still Button and so you can use all its properties and signals, including text property to pass your ueText text.

    As for hiding elements inside, you can use visible property as suggested below:

    UeButton.qml

    Button {
        id: ueButton
        style: ButtonStyle {
            background: Rectangle {
                color: control.pressed ? "#CCC" : "#DEDEDE"
                border.width: 1
                border.color: "#999"
                radius: 3
            }
            label: ColumnLayout {
                id: layout
                spacing: 10
                Image {
                    Layout.alignment: Qt.AlignHCenter
                    source: control.iconSource
                    visible: control.iconSource !== ""
                }
    
                Text {
                    text: control.text
                    visible: control.text !== ""
                }
            }
        }
    }
    

    Now using of this component is similar to regular Button:

    UeButton {
        anchors.centerIn: parent
        text: "Some text"
        iconSource: "data:image/gif;base64,R0lGODlhEAAQAMQAAORHHOVSKudfOulrSOp3WOyDZu6QdvCchPGolfO0o/XBs/fNwfjZ0frl3/zy7////wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAkAABAALAAAAAAQABAAAAVVICSOZGlCQAosJ6mu7fiyZeKqNKToQGDsM8hBADgUXoGAiqhSvp5QAnQKGIgUhwFUYLCVDFCrKUE1lBavAViFIDlTImbKC5Gm2hB0SlBCBMQiB0UjIQA7"
    }
    

    Commenting out text or iconSource will change the button view