Qt 5.14版本中如何自定义QML Gradient的水平方向
在Qt 5.14中为不等宽高的圆角Rectangle实现水平渐变
方案1:用ShaderEffect实现水平渐变
Qt 5.14原生支持ShaderEffect,我们可以通过自定义片段着色器实现从左到右的水平渐变,同时利用Rectangle的clip属性确保渐变内容不会超出圆角边界。
Rectangle { id: outerRect width: 279 height: 8 anchors.verticalCenter: parent.verticalCenter anchors.horizontalCenter: parent.horizontalCenter radius: 7 clip: true // 限制渐变范围在圆角矩形内 ShaderEffect { anchors.fill: parent // 定义渐变停止点,和原代码格式一致 property variant gradientStops: [ { position: 0.0, color: "green" }, { position: 0.25, color: "lightgreen" }, { position: 0.5, color: "yellow" }, { position: 0.75, color: "orange" }, { position: 1.0, color: "red" } ] fragmentShader: " varying highp vec2 qt_TexCoord0; uniform highp float qt_Opacity; uniform variant gradientStops; void main() { highp float x = qt_TexCoord0.x; // 取水平方向的纹理坐标,范围0-1 highp vec4 color = vec4(0.0, 0.0, 0.0, 1.0); // 遍历渐变停止点,计算当前位置的混合颜色 for (int i = 0; i < gradientStops.length(); i++) { var stop = gradientStops[i]; if (x <= stop.position) { if (i == 0) { color = stop.color; } else { var prevStop = gradientStops[i-1]; highp float t = (x - prevStop.position) / (stop.position - prevStop.position); color = mix(prevStop.color, stop.color, t); } break; } else if (i == gradientStops.length() - 1) { color = stop.color; } } gl_FragColor = color * qt_Opacity; } " } }
方案2:用Canvas绘制带圆角的水平渐变
Canvas可以直接绘制自定义路径和渐变,完全不需要依赖高版本Qt的Gradient特性,适合精确控制图形的场景。
Rectangle { id: outerRect width: 279 height: 8 anchors.verticalCenter: parent.verticalCenter anchors.horizontalCenter: parent.horizontalCenter color: "transparent" // 透明底色,让Canvas内容显示 Canvas { anchors.fill: parent onPaint: { var ctx = getContext("2d"); ctx.clearRect(0, 0, width, height); // 创建水平线性渐变:从矩形左边缘到右边缘 var gradient = ctx.createLinearGradient(0, 0, width, 0); gradient.addColorStop(0.0, "green"); gradient.addColorStop(0.25, "lightgreen"); gradient.addColorStop(0.5, "yellow"); gradient.addColorStop(0.75, "orange"); gradient.addColorStop(1.0, "red"); // 绘制带圆角的矩形路径(圆角半径和外层Rectangle一致) var radius = 7; ctx.beginPath(); ctx.moveTo(radius, 0); ctx.lineTo(width - radius, 0); ctx.arc(width - radius, radius, radius, Math.PI * 1.5, Math.PI * 2); ctx.lineTo(width, height - radius); ctx.arc(width - radius, height - radius, radius, 0, Math.PI * 0.5); ctx.lineTo(radius, height); ctx.arc(radius, height - radius, radius, Math.PI * 0.5, Math.PI); ctx.lineTo(0, radius); ctx.arc(radius, radius, radius, Math.PI, Math.PI * 1.5); ctx.closePath(); // 用渐变填充路径 ctx.fillStyle = gradient; ctx.fill(); } } }
内容的提问来源于stack exchange,提问作者user22766422
相关产品推荐
相关产品推荐

