2

I have a custom QQuickItem which I created and I wanted to create a rounded cornered window. So I implemented a QQuickPaintedItem and exported to QML. The problem is that the item's children are expanding by the item's bounding rectangle, which is a rectangle and not a rounded rectangle like I want it. Here's how it looks:

enter image description here

Here is my code:

main.qml

import QtQuick 2.7
import QtQuick.Window 2.2
import mycustomlib 1.0

Window {
    id: wnd
    width: 300
    height: 280
    visible: true
    flags: Qt.FramelessWindowHint
    color: "transparent"
    x: 250
    y: 250

    MyCustomWindow {
        id: playerFrame
        anchors.fill: parent
        radius: 25

        Rectangle {
            color: "beige"
            anchors.margins: 5
            anchors.fill: parent
        }
    }
}

main.cpp

#include <QGuiApplication>
#include <QQmlApplicationEngine>
#include <QUrl>

#include "mycustomwindow.h"

int main(int argc, char *argv[])
{
    QGuiApplication app(argc, argv);

    qmlRegisterType<MyCustomWindow>("mycustomlib", 1, 0, "MyCustomWindow");

    QQmlApplicationEngine engine;
    engine.load(QUrl(QStringLiteral("qrc:/main.qml")));

    return app.exec();
}

mycustomwindow.h

#ifndef MYCUSTOMWINDOW_H
#define MYCUSTOMWINDOW_H

#include <QQuickPaintedItem>

class MyCustomWindow : public QQuickPaintedItem
{
    Q_OBJECT

    Q_PROPERTY(int radius READ radius WRITE setRadius NOTIFY radiusChanged)

public:
    MyCustomWindow(QQuickItem *parent = 0);

    int radius() const;
    void setRadius(int radius);

signals:
    void radiusChanged();

protected:
    virtual void paint(QPainter *pPainter) Q_DECL_OVERRIDE;

private:
    int m_radius;
};

#endif // MYCUSTOMWINDOW_H

mycustomwindow.cpp

#include "mycustomwindow.h"

#include <QPainter>

MyCustomWindow::MyCustomWindow(QQuickItem *parent) :
    QQuickPaintedItem(parent),
    m_radius(0)
{
    setAcceptedMouseButtons(Qt::AllButtons);
}

void MyCustomWindow::paint(QPainter *pPainter)
{
    const QRect myRect(0, 0, width() - 1, height() - 1);
    pPainter->fillRect(myRect, Qt::transparent);
    pPainter->drawRoundedRect(myRect, m_radius, m_radius);
}

int MyCustomWindow::radius() const
{
    return m_radius;
}

void MyCustomWindow::setRadius(int radius)
{
    m_radius = radius;

    emit radiusChanged();
}

What I would like is the child Rectangle's cornered to be clipped by my custom shape(which in this case is a rounded rectangle. Something like this:

enter image description here

Is it possible to achieve something like this in QML?

Jacob Krieg
  • 2,834
  • 15
  • 68
  • 140

1 Answers1

10

I don't know if it is possible with QQuickPaintedItem(it should as you use fill, rather then border only), but without creating custom QSGNode(very hacky), the only way is to use opacitymask:

Rectangle{
    id: mask
    width:100
    height: 100
    radius: 30
    color: "red"
    border.color: "black"
    border.width: 1
}

Item {
    anchors.fill: mask
    layer.enabled: true
    layer.effect: OpacityMask {
        maskSource: mask
    }
    Rectangle {
        anchors.fill: parent
        anchors.margins: 5
        color:"yellow"
    }
}

Which gives you:

masked and clipped rectangle

But using it will be GPU consuming task as the inner item and mask have to be drawn on buffer first and then redrawn on window, so not very good for old mobile or weak embedded devices.

Arpegius
  • 5,817
  • 38
  • 53
  • As I am targeting the desktops I don't think this would be an overhead, would it? – Jacob Krieg Sep 12 '16 at 20:42
  • 1
    @JacobKrieg Yeah, the only flaw is increased memory usage, but as frame buffer could be allocated only on graphic card, it could only appear as increased virtual memory. So don't be shocked that QtQuick app have so large virtual memory usage, with so tiny occupied residential memory. – Arpegius Sep 12 '16 at 21:34
  • 2
    Why is creating a custom QSGNode "very hacky"? – Mitch Sep 13 '16 at 06:14
  • @Mitch becouse it is not well documented and needs loots of classes to be defined. Not even mention creating custom shader. – Arpegius Sep 13 '16 at 13:05
  • 1
    @Arpegius it would be great if you could create suggestions on Jira for how to improve the documentation (i.e what you would like to see explained): bugreports.qt.io – Mitch Sep 13 '16 at 13:50