PyQt 创建色环
PyQt creating color circle
我想给那里的小部件占位符添加一个色圈:
我已经尝试过这个库:
https://gist.github.com/tobi08151405/7b0a8151c9df1a41a87c1559dac1243a
但如果 window 不是样方,色环就不起作用。
我已经尝试过其他解决方案,但没有获取颜色值的方法。
How to create a "Color Circle" in PyQt?
您能否推荐/告诉我一种创建自己的方法,以便我可以将它们添加到那里?
谢谢!
小部件假定其形状始终为正方形;该代码为此提供了自定义 AspectLayout
,但这不是必需的。
这个问题是因为当形状不是正方形时颜色的计算是错误的,因为当一个维度比另一个维度大得多时坐标没有正确映射。例如,如果小部件的宽度比高度高得多,则 x 坐标会“偏移”,因为圆(现在是一个实际的椭圆)居中显示,但颜色函数使用 minimum尺寸。
解决方案是创建一个始终显示在中心的内部 QRect
,并将其用于绘制 和 计算:
class ColorCircle(QWidget):
# ...
def resizeEvent(self, ev: QResizeEvent) -> None:
size = min(self.width(), self.height())
self.radius = size / 2
self.square = QRect(0, 0, size, size)
self.square.moveCenter(self.rect().center())
def paintEvent(self, ev: QPaintEvent) -> None:
# ...
p.setPen(Qt.transparent)
p.setBrush(hsv_grad)
p.drawEllipse(self.square)
p.setBrush(val_grad)
p.drawEllipse(self.square)
# ...
def map_color(self, x: int, y: int) -> QColor:
x -= self.square.x()
y -= self.square.y()
# ...
请注意,该代码使用了 numpy,但它用于那些显然不需要 numpy 性能的应用程序并不真正需要这样一个 巨大 库的函数。
例如,line_circle_inter
使用复杂的方法来计算“光标”(小圆圈)的位置,但这完全没有必要,因为色相和饱和度值已经提供了“可用”坐标: 色相表示圆圈中的角度(从12小时位置开始,逆时针方向),而饱和度是与圆心的距离。
QLineF提供了一个方便的函数,fromPolar()
,它returns给定长度和角度的线:长度将是半径乘以饱和度,角度是色相乘以360(加上90° ,因为角度总是从 3 点开始);然后我们可以在圆心平移那条线,光标将定位在线段的第二个点:
def paintEvent(self, event):
# ...
p.setPen(Qt.black)
p.setBrush(self.selected_color)
line = QLineF.fromPolar(self.radius * self.s, 360 * self.h + 90)
line.translate(self.square.center())
p.drawEllipse(line.p2(), 10, 10)
地图颜色功能可以使用相同的逻辑,但相反:我们从中心到鼠标光标位置构造一条线,然后饱和度是长度除以半径(将值消毒为1.0
,因为这是最大可能值),而色调是线角(如上负 90°)除以 360,并针对正 0.0
-1.0
范围进行消毒。
def map_color(self, x: int, y: int) -> QColor:
line = QLineF(QPointF(self.rect().center()), QPointF(x, y))
s = min(1.0, line.length() / self.radius)
h = (line.angle() - 90) / 360 % 1.
return h, s, self.v
我想给那里的小部件占位符添加一个色圈:
我已经尝试过这个库: https://gist.github.com/tobi08151405/7b0a8151c9df1a41a87c1559dac1243a
但如果 window 不是样方,色环就不起作用。 我已经尝试过其他解决方案,但没有获取颜色值的方法。 How to create a "Color Circle" in PyQt?
您能否推荐/告诉我一种创建自己的方法,以便我可以将它们添加到那里? 谢谢!
小部件假定其形状始终为正方形;该代码为此提供了自定义 AspectLayout
,但这不是必需的。
这个问题是因为当形状不是正方形时颜色的计算是错误的,因为当一个维度比另一个维度大得多时坐标没有正确映射。例如,如果小部件的宽度比高度高得多,则 x 坐标会“偏移”,因为圆(现在是一个实际的椭圆)居中显示,但颜色函数使用 minimum尺寸。
解决方案是创建一个始终显示在中心的内部 QRect
,并将其用于绘制 和 计算:
class ColorCircle(QWidget):
# ...
def resizeEvent(self, ev: QResizeEvent) -> None:
size = min(self.width(), self.height())
self.radius = size / 2
self.square = QRect(0, 0, size, size)
self.square.moveCenter(self.rect().center())
def paintEvent(self, ev: QPaintEvent) -> None:
# ...
p.setPen(Qt.transparent)
p.setBrush(hsv_grad)
p.drawEllipse(self.square)
p.setBrush(val_grad)
p.drawEllipse(self.square)
# ...
def map_color(self, x: int, y: int) -> QColor:
x -= self.square.x()
y -= self.square.y()
# ...
请注意,该代码使用了 numpy,但它用于那些显然不需要 numpy 性能的应用程序并不真正需要这样一个 巨大 库的函数。
例如,line_circle_inter
使用复杂的方法来计算“光标”(小圆圈)的位置,但这完全没有必要,因为色相和饱和度值已经提供了“可用”坐标: 色相表示圆圈中的角度(从12小时位置开始,逆时针方向),而饱和度是与圆心的距离。
QLineF提供了一个方便的函数,fromPolar()
,它returns给定长度和角度的线:长度将是半径乘以饱和度,角度是色相乘以360(加上90° ,因为角度总是从 3 点开始);然后我们可以在圆心平移那条线,光标将定位在线段的第二个点:
def paintEvent(self, event):
# ...
p.setPen(Qt.black)
p.setBrush(self.selected_color)
line = QLineF.fromPolar(self.radius * self.s, 360 * self.h + 90)
line.translate(self.square.center())
p.drawEllipse(line.p2(), 10, 10)
地图颜色功能可以使用相同的逻辑,但相反:我们从中心到鼠标光标位置构造一条线,然后饱和度是长度除以半径(将值消毒为1.0
,因为这是最大可能值),而色调是线角(如上负 90°)除以 360,并针对正 0.0
-1.0
范围进行消毒。
def map_color(self, x: int, y: int) -> QColor:
line = QLineF(QPointF(self.rect().center()), QPointF(x, y))
s = min(1.0, line.length() / self.radius)
h = (line.angle() - 90) / 360 % 1.
return h, s, self.v