Python 3.x PyQt5-HSV梯度而非RGB梯度
我在一个颜色选择器上工作,我创建了一个混合颜色的面板。 面板的第一部分可以创建颜色的色调、色调和阴影,第二部分可以使用两种颜色进行混合 然而,我遇到了一个奇怪的情况,我在小部件上的渐变表示不能反映它正在计算的实际颜色。 在这里你可以看到我使用“绿色”和“粉色”,并且渐变是相同的(RGB渐变?) 我通过计算RGB颜色空间的顶部条插值和HSV中的第二条条插值来实现这一点,这是他们实际给出的结果 这是我的渐变测试(上)与托管代码的绘画程序上的实际颜色混合器(下)的比较,它在HSV中真正显示出来 如何在我的小部件上实现这种渐变过渡表示 代码测试:Python 3.x PyQt5-HSV梯度而非RGB梯度,python-3.x,pyqt5,Python 3.x,Pyqt5,我在一个颜色选择器上工作,我创建了一个混合颜色的面板。 面板的第一部分可以创建颜色的色调、色调和阴影,第二部分可以使用两种颜色进行混合 然而,我遇到了一个奇怪的情况,我在小部件上的渐变表示不能反映它正在计算的实际颜色。 在这里你可以看到我使用“绿色”和“粉色”,并且渐变是相同的(RGB渐变?) 我通过计算RGB颜色空间的顶部条插值和HSV中的第二条条插值来实现这一点,这是他们实际给出的结果 这是我的渐变测试(上)与托管代码的绘画程序上的实际颜色混合器(下)的比较,它在HSV中真正显示出来
def paintEvent(self, event):
green = QColor('#3c552c')
pink = QColor('#d9bdcf')
painter = QPainter(self)
painter.setPen(QPen(Qt.black, 4, Qt.SolidLine))
grad1 = QLinearGradient(20,20,190,20)
grad1.setColorAt(0.0, green)
grad1.setColorAt(1.0, pink)
painter.setBrush(QBrush(grad1))
painter.drawRect(10,10,200,200)
当前使用的代码:
def Mixer_Display(self):
# Display Color with Tint, Tone, Shade
mix_color_tint = str("background-color: qlineargradient(spread:pad, x1:0, y1:0, x2:1, y2:0, stop:0 rgb(%f, %f, %f), stop:1 rgb(255, 255, 255));" % (self.color_n_red, self.color_n_green, self.color_n_blue))
self.layout.color_tint.setStyleSheet(mix_color_tint)
mix_color_tone = str("background-color: qlineargradient(spread:pad, x1:0, y1:0, x2:1, y2:0, stop:0 rgb(%f, %f, %f), stop:1 rgb(127, 127, 127));" % (self.color_n_red, self.color_n_green, self.color_n_blue))
self.layout.color_tone.setStyleSheet(mix_color_tone)
mix_color_shade = str("background-color: qlineargradient(spread:pad, x1:0, y1:0, x2:1, y2:0, stop:0 rgb(%f, %f, %f), stop:1 rgb(0, 0, 0));" % (self.color_n_red, self.color_n_green, self.color_n_blue))
self.layout.color_shade.setStyleSheet(mix_color_shade)
# Display Gradients
mix_gradient_1 = str("background-color: qlineargradient(spread:pad, x1:0, y1:0, x2:1, y2:0, stop:0 rgb(%f, %f, %f), stop:1 rgb(%f, %f, %f));" % (self.color_l1_red, self.color_l1_green, self.color_l1_blue, self.color_r1_red, self.color_r1_green, self.color_r1_blue))
self.layout.gradient_1.setStyleSheet(mix_gradient_1)
mix_gradient_2 = str("background-color: qlineargradient(spread:pad, x1:0, y1:0, x2:1, y2:0, stop:0 rgb(%f, %f, %f), stop:1 rgb(%f, %f, %f));" % (self.color_l2_red, self.color_l2_green, self.color_l2_blue, self.color_r2_red, self.color_r2_green, self.color_r2_blue))
self.layout.gradient_2.setStyleSheet(mix_gradient_2)
mix_gradient_3 = str("background-color: qlineargradient(spread:pad, x1:0, y1:0, x2:1, y2:0, stop:0 rgb(%f, %f, %f), stop:1 rgb(%f, %f, %f));" % (self.color_l3_red, self.color_l3_green, self.color_l3_blue, self.color_r3_red, self.color_r3_green, self.color_r3_blue))
self.layout.gradient_3.setStyleSheet(mix_gradient_3)
您可以通过向渐变添加额外的颜色来模拟HSV渐变。看起来这个插件在色调、饱和度和两种颜色的值之间使用了一个线性插值,因此您可以执行以下操作
from PyQt5 import QtWidgets
from PyQt5.QtCore import Qt
from PyQt5.QtGui import QColor, QPainter, QBrush, QLinearGradient, QPen
import numpy as np
class HSVColorBar(QtWidgets.QFrame):
def __init__(self, c0, c1, parent=None):
super().__init__(parent)
self.c0 = c0
self.c1 = c1
@staticmethod
def color_interpolator(col0, col1, factor):
h0 = col0.hsvHueF()
h1 = col1.hsvHueF()
h1 -= round(h1-h0)
hue = (h0*(1-factor) + h1*factor) % 1
sat = col0.hsvSaturationF() * (1 - factor) + col1.hsvSaturationF() * factor
val = col0.valueF() * (1 - factor) + col1.valueF() * factor
return QColor.fromHsvF(hue, sat, val)
def paintEvent(self, event):
painter = QPainter(self)
painter.setPen(QPen(Qt.black, 4, Qt.SolidLine))
grad1 = QLinearGradient(0, 0, event.rect().width(), 0)
# add intermediate colors to mimic hue mixing
for i in np.linspace(0, 1, 10):
grad1.setColorAt(i, self.color_interpolator(self.c0, self.c1, i))
painter.setBrush(QBrush(grad1))
painter.drawRect(event.rect())
if __name__ == "__main__":
app = QtWidgets.QApplication([])
green = QColor('#3c552c')
pink = QColor('#d9bdcf')
w = HSVColorBar(pink, green)
w.show()
app.exec()
屏幕截图
受你回答的启发,我做了类似的事情 主要内容: 模块:
def HSV_Gradient(self, width, color_left, color_right):
# Colors
left = [color_left[3], color_left[4], color_left[5]]
right = [color_right[3], color_right[4], color_right[5]]
# Conditions
cond1 = right[0] - left[0]
cond2 = (left[0] + 360) - right[0]
cond3 = right[2] - left[1]
cond4 = right[2] - left[2]
# Style String
slider_gradient = "background-color: qlineargradient(spread:pad, x1:0, y1:0, x2:1, y2:0, \n "
"stop:%s rgb(%s, %s, %s), " % (0.000, color_left[0], color_left[1], color_left[2])
unit = 1 / width
for i in range(width):
# Stop
stop = round((i * unit), 3)
# HSV Calculation
if cond1 <= cond2:
hue = left[0] + (stop * cond1)
else:
hue = left[0] - (stop * cond2)
if hue <= 0:
hue = hue + 360
else:
pass
hue = hue / 360
sat = (left[1] + (stop * cond3)) / 100
val = (left[2] + (stop * cond4)) / 100
# HSV to RGB Conversion
rgb = colorsys.hsv_to_rgb(hue, sat, val)
red = round(rgb[0]*255,3)
green = round(rgb[1]*255,3)
blue = round(rgb[2]*255,3)
# String
slider_gradient += "stop:%s rgb(%s, %s, %s), \n " % (stop, red, green, blue)
slider_gradient += "stop:%s rgb(%s, %s, %s) ) " % (1.000, color_right[0], color_right[1], color_right[2])
# Return StyleSheet String
return slider_gradient
def HSV_渐变(自身、宽度、左侧颜色、右侧颜色):
#颜色
左=[color\u left[3],color\u left[4],color\u left[5]]
右=[color\u right[3],color\u right[4],color\u right[5]]
#条件
cond1=右[0]-左[0]
cond2=(左[0]+360)-右[0]
cond3=右[2]-左[1]
cond4=右[2]-左[2]
#样式字符串
slider_gradient=“背景色:qlineargradient(排列:焊盘,x1:0,y1:0,x2:1,y2:0,\n”
“停止:%s rgb(%s,%s,%s),”%(0.000,左颜色[0],左颜色[1],左颜色[2])
单位=1/宽度
对于范围内的i(宽度):
#停止
停止=圆形((i*单位),3)
#HSV计算
如果是cond1,您在哪里使用“实际颜色混合器”?这是另一个人的插件,我只是在它上面选择了相同的颜色来显示颜色差异。因此,这个人所做的可能是使用另一种颜色插值,可能是基于HSV颜色空间。如果你知道该插件的来源,你可以在其代码中找到它是如何完成的。我不知道渐变在哪里它来自:\n插件名是什么?可以不使用numpy模块吗?它不适用于我正在使用的绘图程序。numpy已经在大多数系统中可用,因为它是一个非常常用的模块。您可以“手动”执行相同的操作,但速度会慢得多。我能想到的唯一替代方法是自己做一个小Cython模块进行插值。在本例中,numpy用于np.linspace(0,1,10)中I的for循环。
。您可以用范围(11)中I的:I=I/10…
def HSV_Gradient(self, width, color_left, color_right):
# Colors
left = [color_left[3], color_left[4], color_left[5]]
right = [color_right[3], color_right[4], color_right[5]]
# Conditions
cond1 = right[0] - left[0]
cond2 = (left[0] + 360) - right[0]
cond3 = right[2] - left[1]
cond4 = right[2] - left[2]
# Style String
slider_gradient = "background-color: qlineargradient(spread:pad, x1:0, y1:0, x2:1, y2:0, \n "
"stop:%s rgb(%s, %s, %s), " % (0.000, color_left[0], color_left[1], color_left[2])
unit = 1 / width
for i in range(width):
# Stop
stop = round((i * unit), 3)
# HSV Calculation
if cond1 <= cond2:
hue = left[0] + (stop * cond1)
else:
hue = left[0] - (stop * cond2)
if hue <= 0:
hue = hue + 360
else:
pass
hue = hue / 360
sat = (left[1] + (stop * cond3)) / 100
val = (left[2] + (stop * cond4)) / 100
# HSV to RGB Conversion
rgb = colorsys.hsv_to_rgb(hue, sat, val)
red = round(rgb[0]*255,3)
green = round(rgb[1]*255,3)
blue = round(rgb[2]*255,3)
# String
slider_gradient += "stop:%s rgb(%s, %s, %s), \n " % (stop, red, green, blue)
slider_gradient += "stop:%s rgb(%s, %s, %s) ) " % (1.000, color_right[0], color_right[1], color_right[2])
# Return StyleSheet String
return slider_gradient