Как де-насытить цвет, определенный RGB в декларативном QML

#qt #colors #qml #qtquick2 #hsl

#qt #Цвет #qml #qtquick2 #hsl

Вопрос:

Используя QtQuick, можно ли взять существующий цвет, определенный RGB, и обесцветить его, не прибегая к Javascript?

Комментарии:

1. Если вы просто хотите уменьшить насыщенность чего-либо на экране, вы можете использовать doc.qt.io/qt-5/qml-qtgraphicaleffects-desaturate.html

Ответ №1:

 function desaturate(colorString)
{
    let c = Qt.darker(colorString, 1.0);
    return Qt.hsla(c.hslHue, 0.0, c.hslLightness, c.a);
}
  

Комментарии:

1. Qt.darker Действительно ли это единственный способ получить тип цвета из строки в JS?

2. Ну, вы могли бы использовать Qt.lighter 😉

Ответ №2:

Видя, как QtQuick работает поверх движка Javascript, я бы сказал, что невозможно что-либо сделать в QML, не прибегая к Javascript.

Чтобы настроить насыщенность, вам нужно будет преобразовать RGB в цвет HSL, а затем обратно в RGB. QML имеет Qt.hsla() для последнего, но в прошлый раз, когда я проверял, он не обеспечивал преобразование из RGB в HSL, поэтому я закончил использовать это:

 function rgbToHsl(r, g, b) {
  r /= 255
  g /= 255
  b /= 255
  var max = Math.max(r, g, b), min = Math.min(r, g, b)
  var h, s, l = (max   min) / 2
  if (max == min) {
    h = s = 0
  } else {
    var d = max - min
    s = l > 0.5 ? d / (2 - max - min) : d / (max   min)
    switch (max) {
    case r:
      h = (g - b) / d   (g < b ? 6 : 0)
      break
    case g:
      h = (b - r) / d   2
      break
    case b:
      h = (r - g) / d   4
      break
    }
    h /= 6;
  }
  return {"h":h, "s":s, "l":l};
}
  

Итак, вы в основном:

 var ic = yourRGBColor.toString()
var r = parseInt(ic.substr(1, 2), 16)
var g = parseInt(ic.substr(3, 2), 16)
var b = parseInt(ic.substr(5, 2), 16)
var hsl = rgbToHsl(r, g, b)
hsl.s *= .5 // desaturate 50%
yourRGBColor = Qt.hsla(hsl.h, hsl.s, hsl.l, 1)
  

Ответ №3:

Просто измените цвет hsvSaturation или hslSaturation свойство в зависимости от вашей цветовой модели.

Пример Test.qml , который де-насыщает синий прямоугольник постепенно каждую секунду (выполняется с qmlscene Test.qml ):

 import QtQuick 2.7
Item {
    width: 100
    height: 100
    Rectangle {
        anchors.fill: parent
        objectName: "precious"
        color: "#0000FF"
        Timer {
            running: true
            repeat: true
            onTriggered: parent.color.hslSaturation *= 0.8;
        }
    }
}
  

Скрытые в большом количестве текста, между двумя блоками кода, эти свойства фактически задокументированы в color QML Basic Type . Они, по-видимому, соответствуют qreal версиям свойств цветового компонента в C (имена, оканчивающиеся на ...F() ).


Как утверждает @dtech, onTriggered:... юридически это уже строка JavaScript. Если необходимо, вы также можете пройти по строке в C , найти атрибут элемента и изменить там свойство.

Пример main.cpp , показывающий вышеизложенное Test.qml , который начинается с уже очень де-насыщенного (чисто на C ) синего прямоугольника, затем постепенно его де-насыщая (все еще выполняется в QML / JavaScript):

 #include <QGuiApplication>
#include <QQuickView>
#include <QQuickItem>

int main(int argc, char *argv[])
{
    QGuiApplication app(argc, argv);
    QQuickView view(QUrl(QLatin1String("qrc:/Test.qml")));
    view.show();
    if ( QObject * rectangle = view.rootObject()->findChild<QObject*>("precious") )
    {
        qreal h, s, l, a;
        rectangle->property("color").value<QColor>().getHslF( amp;h, amp;s, amp;l, amp;a );
        s *= 0.2;
        rectangle->setProperty( "color", QVariant::fromValue(QColor::fromHsvF( h, s, l, a )) );
    }
    return app.exec();
}
  

Теперь вы можете удалить видимую строку JavaScript из Test.qml .


Обратите внимание, что я демонстрирую очень грубую цветовую анимацию. Существует специальный ColorAnimation инструмент для улучшения.