Reputation: 29
I would like to create a QWidget/QDialog that looks like this:
Color Circle
or:
Windows Color Picker
I am aware of QColorDialog
, but i do not want to use it.
Upvotes: 1
Views: 3548
Reputation: 51
I know this is a old question,
but since the only answer has pretty bad performance, here is my version.
It uses two gradients laid on top of each other instead of rendering each point in the widget separately.
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())
a fully functional version (with signals, set/get functions) can be found at this gist https://gist.github.com/tobi08151405/7b0a8151c9df1a41a87c1559dac1243a
Upvotes: 5
Reputation: 1847
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()
Output:
Upvotes: 3