如何在 PyQt 中创建“色环”?

Posted

技术标签:

【中文标题】如何在 PyQt 中创建“色环”?【英文标题】:How to create a "Color Circle" in PyQt? 【发布时间】:2018-06-06 12:43:27 【问题描述】:

我想创建一个如下所示的 QWidget/QDialog:

Color Circle 或:Windows Color Picker

我知道QColorDialog,但我不想使用它。

【问题讨论】:

【参考方案1】:

HSV Color Space

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()

输出:

【讨论】:

【参考方案2】:

我知道这是一个老问题, 但由于唯一的答案性能很差,这是我的版本。 它使用两个相互叠加的渐变,而不是单独渲染小部件中的每个点。

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())

可以在此 gist https://gist.github.com/tobi08151405/7b0a8151c9df1a41a87c1559dac1243a 找到功能齐全的版本(带有信号、设置/获取功能)

【讨论】:

以上是关于如何在 PyQt 中创建“色环”?的主要内容,如果未能解决你的问题,请参考以下文章

如何在 PyQt 中创建可折叠的盒子

如何在 QML 中创建 PyQT 注册类型的动态实例

如何在 Pyqt 中创建可调整大小的布局 UI?

如何在 Python 函数中创建简单的 PyQt 弹出窗口并在其末尾关闭?

在 PyQt 中创建图像浏览器?从哪儿开始? [关闭]

设置在主类的子类中创建的 PyQt5 小部件的属性