Я хочу получить цвет Visual в произвольной позиции в 0,0 -
Код: Выделить всё
1.0Это может потребоваться для правильного вычисления новых промежуточных остановок между существующими или для получения цвета в определенной точке, чтобы использовать его в качестве ссылки на отображение в градиенте. which seemed reasonable.
Gradients can have many colors set at different points, which can be set by using QVariantAnimation.setKeyValueAt().
They also can have no 0.0 or 1.0 stops, meaning that if, for example, the first stop is at 0.2 and the last is at 0.8, the start и конечные значения анимации должны быть установлены также с относительным первым и последним цветом.
Моя первоначальная попытка состояла в том, чтобы создать временную анимацию, а затем установить его значения ключей на основе градиентных остановок: использование setcurrenttime () на основе компьютерной позиции в продолжительности анимации () позволяет получить код. Реализация: < /p>
Обратите внимание, что я не могу написать код C ++, поэтому я предоставлю код на основе Python для следующих примеров. Ответы на основе C ++ также будут хорошо приняты, хотя.
Код: Выделить всё
def gradientColorAt(grad, pos):
if pos = 1:
return grad.stops()[-1][1]
ani = QVariantAnimation()
ani.setDuration(1000)
startDone = False
for stop, color in grad.stops():
if not startDone:
startDone = True
ani.setStartValue(color)
if not stop:
continue
ani.setKeyValueAt(stop, color)
if stop < 1:
ani.setEndValue(color)
ani.setCurrentTime(round(1000 * pos))
return ani.currentValue()
рассматривает следующий пример:
from PyQt5.QtCore import *
from PyQt5.QtGui import *
from PyQt5.QtWidgets import *
app = QApplication([])
win = QWidget()
lay = QVBoxLayout(win)
grad = QLinearGradient(0, 0, 1, 0)
grad.setCoordinateMode(grad.ObjectBoundingMode)
grad.setColorAt(1, Qt.green)
transBlack = QColor(Qt.transparent)
transRed = QColor(255, 0, 0, 0)
pal = app.palette()
for color in (transBlack, transRed):
grad.setColorAt(0, color)
pal.setBrush(QPalette.Window, QBrush(grad))
widget = QWidget()
widget.setAutoFillBackground(True)
widget.setPalette(pal)
lay.addWidget(widget)
win.resize(400, 400)
win.show()
app.exec()
И вот результат:
Предлагает аналогичные узор (такие that.
Nonetheless, the issue is that the above QVariantAnimation attempt does not follow the same pattern, as it simply uses an internal interpolator that linearly evaluates all color components.
Let's add the gradientColorAt() function to the above code, along with the following class:
Код: Выделить всё
class GradientViewer(QWidget):
def __init__(self, gradient):
super().__init__()
self.gradient = QLinearGradient(gradient)
def paintEvent(self, event):
qp = QPainter(self)
width = self.width()
height = self.height()
for x in range(width + 1):
qp.setPen(gradientColorAt(self.gradient, x / width))
qp.drawLine(x, 0, x, height)
< /code>
Затем добавьте соответствующие экземпляры в макет с использованием тех же градиентов: < /p>
...
# replace the above for loop
for color in (transBlack, transRed):
grad.setColorAt(0, color)
pal.setBrush(QPalette.Window, QBrush(grad))
widget = QWidget()
widget.setAutoFillBackground(True)
widget.setPalette(pal)
lay.addWidget(widget)
# custom widget using the same gradient
lay.addWidget(GradientViewer(grad))
...
. Источники, которые выглядели многообещающими: механизм Raster Painting имеет функцию GenerateGradientColartable () (см. Это в браузере кода), которая, по -видимому, используется для создания растрового кэша, основанного на арбитральном размере цветовых интерполяций в градиенте. Qvariantanimation Подкласс, основанный на этом коде: < /p>
Код: Выделить всё
class QColorInterpolator(QVariantAnimation):
def interpolated(self, c1, c2, pos):
if pos = 1:
return c2
first = c1.rgba64()
first = QRgba64.fromRgba64(
first.red(), first.green(), first.blue(), (first.alpha() * 256) >> 8
).premultiplied()
second = c2.rgba64()
second = QRgba64.fromRgba64(
second.red(), second.green(), second.blue(), (second.alpha() * 256) >> 8
).premultiplied()
r1 = first.red() 16,
)
< /code>
Очевидно, что приведенный выше класс на самом деле не нужен, так как интерполяция может быть достигнута с помощью относительных шагов между остановками. Единственным преимуществом является возможность использования интерполированного () Unfortunately, my limited understanding of color composition and alpha premultiplication seem to show its problems: replacing QVariantAnimation with QColorInterpolator in the above gradientColorAt() function will give exactly the same result as in using QT.TransParent .
Рабочее решение, не совсем эффективное
Прямо сейчас единственное рабочее решение, которое я выпустил, - это использовать внутренний кэш Qimages, каждый из которых соответствует возможным промежуточным градиентам (каждая диапазон между существующими остановками), покраски на его градиент, и затем использует Qimage's Pilescolor (Feekercolor). вычисленной позиции: < /p>
Код: Выделить всё
class QColorInterpolator(QVariantAnimation):
_imageCache = {}
def _createCacheGradient(self, c1, c2):
g = QLinearGradient(0, 0, 1024, 0)
g.setStops([(0, c1), (1, c2)])
image = QImage(1024, 1, QImage.Format_ARGB32)
image.fill(Qt.transparent)
qp = QPainter(image)
qp.fillRect(image.rect(), g)
qp.end()
return image
def interpolated(self, c1, c2, pos):
if pos = 1:
return c2
if c1 == c2:
return c1
key = c1.rgba64(), c2.rgba64()
if key in self._imageCache:
gradImg = self._imageCache[key]
else:
self._imageCache[key] = gradImg = self._createCacheGradient(c1, c2)
return gradImg.pixelColor(round(1023 * pos), 0)
/> Хотя последняя попытка работает как ожидалось, мне это не очень нравится, по следующим причинам: < /p>
- Насколько я могу понять, QT уже создает внутренний кэш «цветовой таблицы», и, хотя он, очевидно, не может быть извне, создание разделенных Qimages не очень эффективно; предполагал один, основанный на данных пикселей Qimage;
- Из -за всего вышеперечисленного, любые временные вычисления промежуточных цветов потребуются для создания Qvariantanimation, которую я бы предпочел избегать;
Код: Выделить всё
ColorInterpolationПодробнее здесь: https://stackoverflow.com/questions/795 ... -qgradient
Мобильная версия