自定义形状后剪辑自定义 qml 项的子项 [英] Clip children of custom qml item after custom shape

查看:35
本文介绍了自定义形状后剪辑自定义 qml 项的子项的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我创建了一个自定义的 QQuickItem,我想创建一个圆角窗口.所以我实现了一个 QQuickPaintedItem 并导出到 QML.问题是项目的子项正在扩展项目的边界矩形,这是一个矩形而不是我想要的圆角矩形.这是它的外观:

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:

这是我的代码:

ma​​in.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
        }
    }
}

ma​​in.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();
}

我想要的是子 Rectangle 的角落被我的自定义形状(在这种情况下是一个圆角矩形.像这样:

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:

是否可以在 QML 中实现类似的功能?

Is it possible to achieve something like this in QML?

推荐答案

我不知道 QQuickPaintedItem 是否可行(它应该在您使用填充时,而不是仅使用边框),但没有创建自定义 QSGNode(非常hacky),唯一的方法是使用 opacitymask:

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"
    }
}

这给了你:

但是使用它会消耗 GPU 资源,因为必须先在缓冲区上绘制内部项和掩码,然后再在窗口上重新绘制,因此对于旧的移动设备或弱嵌入式设备来说不是很好.

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.

这篇关于自定义形状后剪辑自定义 qml 项的子项的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆