答案 0 :(得分:3)
我知道这是一个老问题,
但由于唯一的答案性能很差,这是我的版本。
它使用两个叠加在一起的渐变,而不是分别渲染小部件中的每个点。
class ColorCircle(QWidget):
def __init__(self, parent=None) -> None:
super().__init__(parent=parent)
self.radius = 0
def resizeEvent(self, ev: QResizeEvent) -> None:
self.radius = min([self.width()/2, self.height()/2])
def paintEvent(self, ev: QPaintEvent) -> None:
center = QPointF(self.width()/2, self.height()/2)
p = QPainter(self)
hsv_grad = QConicalGradient(center, 90)
for deg in range(360):
col = QColor.fromHsvF(deg / 360, 1, self.v)
hsv_grad.setColorAt(deg / 360, col)
val_grad = QRadialGradient(center, self.radius)
val_grad.setColorAt(0.0, QColor.fromHsvF(0.0, 0.0, self.v, 1.0))
val_grad.setColorAt(1.0, Qt.transparent)
p.setPen(Qt.transparent)
p.setBrush(hsv_grad)
p.drawEllipse(self.rect())
p.setBrush(val_grad)
p.drawEllipse(self.rect())
可以在此要点中找到功能齐全的版本(带有信号、设置/获取功能)https://gist.github.com/tobi08151405/7b0a8151c9df1a41a87c1559dac1243a
答案 1 :(得分:2)
from PyQt5 import QtWidgets, QtCore, QtGui
import sys
import numpy as np
class ColorCircle(QtWidgets.QWidget):
def __init__(self):
super().__init__()
self.radius = 100.
self.setFixedSize(200, 200)
def paintEvent(self, ev):
super().paintEvent(ev)
p = QtGui.QPainter(self)
for i in range(self.width()):
for j in range(self.height()):
color = QtGui.QColor(255, 255, 255, 255)
h = (np.arctan2(i-self.radius, j-self.radius)+np.pi)/(2.*np.pi)
s = np.sqrt(np.power(i-self.radius, 2)+np.power(j-self.radius, 2))/self.radius
v = 1.0
if s < 1.0:
color.setHsvF(h, s, v, 1.0)
p.setPen(color)
p.drawPoint(i, j)
if __name__ == '__main__':
app = QtWidgets.QApplication(sys.argv)
w = ColorCircle()
w.show()
app.exec()
输出: