You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何让QML ShaderEffect作用于Drawer和Popup组件

如何让QML ShaderEffect作用于Drawer和Popup组件

嘿,我来帮你搞定这个问题!你现在遇到的情况是,ShaderEffect只作用在了rect这个矩形上,而Drawer、顶部的按钮这些组件没被处理,对吧?

问题根源

你当前的ShaderEffect把rect作为了输入源,但Drawer、按钮这些组件和rect是同级的,不在rect的层级结构里,自然不会被 shader 处理。而且更关键的是,Qt Quick Controls的Drawer默认会渲染在Window的overlay层,这个层级比普通组件更高,就算你调整ShaderEffect的z值也不一定能覆盖到它。

解决方案

这里给你两种靠谱的实现方式,你可以根据自己的场景选:

方案一:用Window的layer捕获整个窗口内容

我们可以开启Window的layer功能,把整个窗口的所有渲染内容都作为ShaderEffect的输入,这样不管是普通组件还是Drawer、Popup这类特殊组件,都会被包含进来。修改后的代码如下:

import QtQuick 2.15
import QtQuick.Window 2.15
import QtQuick.Controls 2.15

Window {
    width: 1024
    height: 600
    visible: true
    // 开启Window的layer,捕获整个窗口的渲染内容
    layer.enabled: true

    Rectangle {
        id: rect
        anchors.fill: parent
        color: "gray"

        Text {
            anchors.centerIn: parent
            text: qsTr("Hello")
            font.pixelSize: 40
            color: "blue"
        }
    }

    Drawer {
        id: drawer
        width: 0.66 * rect.width
        height: rect.height

        Label {
            text: "Content goes here!"
            anchors.centerIn: parent
        }
    }

    Button {
        id: drawerButton
        text: "Open drawer"
        anchors.right: parent.right

        onClicked: {
            drawer.open();
        }
    }

    Loader {
        id: effectLoader
        sourceComponent: shaderComponent
        anchors.fill: parent
        // 设置足够高的z值,确保ShaderEffect在最顶层
        z: 9999
    }

    Component {
        id: shaderComponent
        ShaderEffect {
            id: shader
            // 绑定到Window的layer纹理,获取整个窗口的渲染内容
            property variant source: window.layer.texture
            fragmentShader: "
            varying highp vec2 qt_TexCoord0;
            uniform sampler2D source;
            uniform lowp float qt_Opacity;
            void main() {
                gl_FragColor = texture2D(source, qt_TexCoord0) * vec4(0.2, 0.2, 0.0, 0.1) * qt_Opacity;
            }"
        }
    }
}

方案二:把所有内容放进根Item,用其layer作为源

如果你不想开启Window的layer,也可以创建一个覆盖整个Window的根Item,把所有组件(包括修改parent后的Drawer)都放到这个Item里,然后开启它的layer,再让ShaderEffect以这个layer的纹理为输入:

import QtQuick 2.15
import QtQuick.Window 2.15
import QtQuick.Controls 2.15

Window {
    width: 1024
    height: 600
    visible: true

    // 根Item,包含所有需要被shader处理的内容
    Item {
        id: rootContent
        anchors.fill: parent
        layer.enabled: true

        Rectangle {
            id: rect
            anchors.fill: parent
            color: "gray"

            Text {
                anchors.centerIn: parent
                text: qsTr("Hello")
                font.pixelSize: 40
                color: "blue"
            }
        }

        Button {
            id: drawerButton
            text: "Open drawer"
            anchors.right: parent.right

            onClicked: {
                drawer.open();
            }
        }

        // 修改Drawer的parent为rootContent,确保它被包含在layer范围内
        Drawer {
            id: drawer
            parent: rootContent
            width: 0.66 * rect.width
            height: rect.height

            Label {
                text: "Content goes here!"
                anchors.centerIn: parent
            }
        }
    }

    Loader {
        id: effectLoader
        sourceComponent: shaderComponent
        anchors.fill: parent
        z: 9999
    }

    Component {
        id: shaderComponent
        ShaderEffect {
            id: shader
            property variant source: rootContent.layer.texture
            fragmentShader: "
            varying highp vec2 qt_TexCoord0;
            uniform sampler2D source;
            uniform lowp float qt_Opacity;
            void main() {
                gl_FragColor = texture2D(source, qt_TexCoord0) * vec4(0.2, 0.2, 0.0, 0.1) * qt_Opacity;
            }"
        }
    }
}

小提醒

开启layer会带来一定的性能开销,尤其是在性能有限的设备上,所以如果你的界面比较复杂,需要平衡好效果和性能。另外,一定要确保ShaderEffect所在的Loader的z值足够大,保证它在所有组件的最顶层,这样处理后的内容才能完全覆盖原始内容。

备注:内容来源于stack exchange,提问作者Evan Krause

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.23 10:22:34