Многоцветный градиент в QML - PullRequest
       92

Многоцветный градиент в QML

0 голосов
/ 01 августа 2020

Я начал изучать структуру Qt и хотел создать фон с многоцветным градиентом (как на изображении ниже) для окна:

Пример изображения MutiColored Gradient Image

Я просмотрел официальную документацию по типу Linear/Conical/Radial/Shape Gradient QML, а также Google. Но я не видел никакого варианта для достижения этого.

Есть ли другой способ сделать это возможным? Предпочтительно в QML.

Изменить 1:

Как указано в комментариях, GradientStop можно использовать для нескольких цветов. Но его нельзя использовать для получения результата, как на данном изображении.

Ответы [ 2 ]

1 голос
/ 02 августа 2020

Ответ Игоря хороший. Я обнаружил, что Qt на самом деле предоставляет пример, который тоже может быть полезен. Посмотрите их пример Squircle . Я не буду воспроизводить все это здесь, но он создает QQuickItem в C ++ и выполняет на нем некоторую пользовательскую визуализацию OpenGL. Затем объект можно использовать в QML.

1 голос
/ 02 августа 2020

Сначала ознакомьтесь с примером Qt quick\scenegraph\fboitem. Он демонстрирует создание настраиваемого элемента управления QML с бэкэндом C ++ / OpenGL.

Также вы можете реализовать его с помощью ShaderEffect элемента управления QML. Я рекомендую этот сайт https://www.shadertoy.com/new для отладки ваших шейдеров. Также вы можете использовать, например, Canvas для передачи массивов вашему шейдеру в виде текстуры (ShaderEffect не позволяет передавать массивы обычным образом, https://bugreports.qt.io/browse/QTBUG-50493).

Вот Возможная реализация вашего управления с динамикой c количество точек, цвета и позиции.

import QtQuick 2.12
import QtQuick.Controls 2.5

ApplicationWindow {
    id: window
    visible: true
    width: 640
    height: 480
    title: "Custom gradient"

    Item {
        anchors.fill: parent

        layer.enabled: true
        layer.effect: ShaderEffect {
            readonly property var dataTex: dataCanvas
            readonly property int count: dataCanvas.colors.length

            fragmentShader: "
                  varying highp vec2 qt_TexCoord0;
                  uniform lowp float qt_Opacity;
                  uniform sampler2D dataTex;
                  const uniform lowp int count;
                  void main() {
                      vec3 col = 0.0;

                      for (int i = 0; i < count; i++) {
                          vec4 color = texture2D(dataTex, vec2(i / (float)count + 0.01, 0.0));
                          vec2 point = texture2D(dataTex, vec2(i / (float)count + 0.01, 1.0)).rg;

                          float dist = distance(qt_TexCoord0, point);
                          col += color * (1.0 - dist);
                      }

                      gl_FragColor = vec4(col, 1.0);
                  }
        ";
        }

        // Because ShaderEffect doesn't allow passing arrays to shader, we will
        // convert arrays to graphical representation and pass them as texture.
        Canvas {
            id: dataCanvas
            readonly property var colors: ["cyan", "red", "green", "darkblue", "yellow"]
            readonly property var positions: [Qt.point(0,0),
                                              Qt.point(10, parent.height - 20),
                                              Qt.point(parent.width / 2, parent.height / 4),
                                              Qt.point(parent.width, 0),
                                              Qt.point(parent.width, parent.height)]

            height: 2
            width: colors.length
            antialiasing: false
            visible: false

            onPaint: {
                if (colors.length !== positions.length) {
                    console.error("Array size of 'colors' doesn't equal array size of 'positions'");
                    return;
                }

                var ctx = getContext("2d");
                ctx.reset();
                ctx.lineWidth = 1;

                for (var i = 0; i < colors.length; i++) {
                    ctx.beginPath();
                    ctx.strokeStyle = colors[i];
                    ctx.moveTo(i, 0);
                    ctx.lineTo(i+1, 0);
                    ctx.stroke();
                    ctx.closePath();

                    ctx.beginPath();
                    ctx.strokeStyle = Qt.rgba(positions[i].x / parent.width, positions[i].y / parent.height, 0, 1);
                    ctx.moveTo(i, 1);
                    ctx.lineTo(i+1, 1);
                    ctx.stroke();
                    ctx.closePath();
                }
            }
        }
    }
}

Вот так это выглядит введите описание изображения здесь

Я не гуру OpenGL, поэтому этот код не идеален. Буду рад, если кто-нибудь отредактирует этот ответ, чтобы он стал лучше.

...