grunk
grunk

Reputation: 14938

QML : Rounded rectangle with border

I have to create some "tabs" in QML which should have rounded corners at the top and a border all over it :

enter image description here

I managed to create the rounded rectangle by using 2 rectangles :

(the tabs are part of a listview)

 ListView {
    id: listView
    anchors.fill: parent
    orientation: ListView.Horizontal
    spacing: Math.floor(0.60 * parent.width / 100)

    model: TabsModel{}

    delegate: TabsDelegate {

        height: parent.height

    }
}

The delegate which is the actual tab :

Item {
    id: root

    width: 200

    Rectangle {
        id: topRect
        anchors.fill: parent
        radius: 5
        color: backgroundColor
        /*border.width: 1
        border.color: borderColor*/
    }

   Rectangle {
        id: bottomRect
        anchors.bottom: parent.bottom
        anchors.left: topRect.left
        anchors.right: topRect.right
        height: 1 / 2 * parent.height
        color: backgroundColor
        /*border.width: 1
        border.color: borderColor*/
    }

    Text {
        id: text
        anchors.verticalCenter: parent.verticalCenter
        anchors.left: parent.left
        anchors.leftMargin: spaceBefore
        text: label
        color: textColor
    }
}

With this code i have the following result :

enter image description here

Obviously if i add the borders , i end up with with a border in the middle of my tabs : enter image description here

Any ideas how i can manage to get what i want in qml ?

Upvotes: 2

Views: 11480

Answers (3)

Andras
Andras

Reputation: 24

I have recently needed a rounded rectangle with different radius in each corner and with border, so I implemented one. It depends on Qt 6 and uses shaders so it doesn't work with software rendering, still I hope it helps some people. The code is available at https://gitlab.com/Akeras/QmlRoundedRectangle

Upvotes: 1

dtech
dtech

Reputation: 49289

You could use a single rectangle if you can get away with tucking its bottom edge under something on the GUI. That's about all you can do out of the box as QML doesn't support custom corner angling. Granted, you can try covering that line up with yet another third rectangle, but that's clearly the wrong and messy approach you shouldn't be taking.

Otherwise you will have to do manual painting.

There is a number of options here.:

1 - use Canvas to draw from QML, and use that graphic with a BorderImage, which will allow you to use the same, single time painted elements to drive an arbitrary size label. You can also use an image generated by a 3rd party program, but drawing it in QML is more flexible

2 - use QQuickPaintedItem and draw the entire tab with C++ and QPainter

3 - implement a proper QQuickItem that generates the needed geometry and renders the item efficiently with the QML scene graph in OpenGL.

Upvotes: 1

augre
augre

Reputation: 2051

You can simply add another Rectangle (between bottomRect and text) to hide the middle border:

Rectangle {
    anchors {
        fill: bottomRect
        leftMargin: bottomRect.border.width
        bottomMargin: bottomRect.border.width
        rightMargin: bottomRect.border.width
    }
    color: backgroundColor
}

Upvotes: 3

Related Questions