Jay
Jay

Reputation: 14441

QML Canvas clipping - non rectangular possible?

Is it possible to display non rectangular items in an app?

The top right edge of each element is clipped:

enter image description here

I turned off clipping on the canvas element and set the clipping region of the context. I even allowed for the stroke drawing outside the path. Here's what I'm using to draw it:

Canvas
{
    //id: root
    // canvas size
    height: parent.height - 8
    width: height
    anchors.top: parent.top + 4
    clip: false
    z: index + 1
    // handler to override for drawing
    onPaint:
    {
        // get context to draw with
        var ctx = getContext("2d")
        ctx.reset();

        // path that includes 1 pixel margin on all sides
        ctx.beginPath()
        ctx.moveTo( 8, 0 )
        ctx.lineTo( width + 4, 0 )
        ctx.lineTo( width - 4, height )
        ctx.lineTo( 0, height )
        ctx.closePath()
        ctx.clip();

        // setup the stroke
        ctx.lineWidth = 2
        ctx.strokeStyle = "white"
        ctx.beginPath()
        ctx.moveTo( 9, 1 )
        ctx.lineTo( 9 + width, 1 )
        ctx.lineTo( 1 + width, height - 1 )
        ctx.lineTo( 1, height - 1 )
        ctx.closePath()
        ctx.fillStyle = (roleStatus.toLowerCase().indexOf("success")!==-1) ? "green" : "red"
        ctx.fill()
        ctx.stroke()
    }
}

This will be used on Windows and android.

Thanks

Upvotes: 0

Views: 1505

Answers (2)

Jay
Jay

Reputation: 14441

I was unable to find a way to draw outside the bounds of the item. I was able to achieve the effect I wanted though. I drew the polygon within the bounds of the item and set the 'spacing' property of the ListView to a negative value. This overlaps the drawn items to achieve the desired look:

enter image description here

Upvotes: 0

mike510a
mike510a

Reputation: 2168

Yes... You can use PaintedItem to paint directly on items using Native Paint tools from C++ like QPainterPath

check out http://doc.qt.io/qt-5/qtquick-customitems-painteditem-example.html

the reason that your canvas is clipping is due to the fact that you are drawing width + 4 which should be (width - 8), but since you move to (8,0) first, then you end up drawing an extra 4 pixels too far. try either moving the item over 4 pixels by doing moveTo(4,0) or make the line shorter by doing just width instead of width + 4

Also check out : anchors.fill: parent which will work better in your case most likely.

The way that I avoid crazy bugs like this is by not ever hard coding width, height, x or y into my application.. instead use percentages such as

(parent.width * 0.25) to get 1/4 of the parent

Here's ONE way you could fix your code...

Canvas
{
    //id: root
    // canvas size
    height: parent.height * 0.95
    width: height
    anchors.top: parent.top
    clip: false
    z: index + 1
    // handler to override for drawing
    onPaint:
    {
        // get context to draw with
        var ctx = getContext("2d")
        ctx.reset();

        // path that includes 1 pixel margin on all sides
        ctx.beginPath()
        ctx.moveTo( width * 0.1, 0 )
        ctx.lineTo( width * 0.9, 0 )
        ctx.lineTo( width * 0.7, height )
        ctx.lineTo( 0, height )
        ctx.closePath()
        ctx.clip();
        /* etc etc */
    }
}

Upvotes: 1

Related Questions