Créez un sélecteur de couleurs pour la roue chromatique avec Python + Qt (PySide)

C'était peu probable et inattendu, j'ai donc créé un widget pour le sélecteur de couleurs de la roue chromatique. Au départ, lorsque j'ai décrit le traitement de bas niveau avec la colle en langage C, il est devenu au ralenti lorsqu'il est agrandi et affiché dans le contrôle de fonctionnement pour un moniteur haute résolution, et si j'ai optimisé la bibliothèque Qt et le style Python, cela fonctionne sans problème. Il est venu pour être. Si vous utilisez Python, vous devriez apprendre le style Python.

La gradation de la boîte de couleur de saturation et de luminosité au centre est réalisée en synthétisant les deux gradations de saturation et de transparence. C'est la méthode introduite sur les tableaux d'affichage à l'étranger.

Je me suis inscrit auprès de PyPI. Vous pouvez l'installer avec pip etc. J'ai enregistré la source sur GitHub. https://github.com/tokyo-noctambulist/colorpicker.git

(Mis à jour le 07/03/2017) Correction d'un bug qui détruisait la valeur α. Changement en mosaïque BG pour refléter la valeur α sur l'échantillon de couleur et la roue chromatique Changer la valeur à copier lors de la spécification de la couleur

échantillon

image

Dans sample.py, les deux cercles de couleur sont liés et affichés.


Brève explication

Je me suis inscrit auprès de PyPI. Vous pouvez l'installer avec pip etc.

function


pip install colorpicker #install

from colorpicker import *

colorCircle = QHueCircleWidget(self)
color = colorCircle.getColor() #Obtenez de la couleur
colorCircle.setColor(QColor(255,100,10,200)) #Définir la couleur

colorCircle.colorChanged.connect(onUpdateColor) #signal-slot

Vous pouvez le redimensionner avec resize (). Cependant, cela ne fonctionnera pas correctement si le rapport hauteur / largeur n'est pas réglé sur 1: 1. (Non compatible avec l'état elliptique orz)


QHueCircleWidget.py


# coding:utf-8
from __future__ import division, print_function, unicode_literals, absolute_import
# noinspection PyUnresolvedReferences
from future_builtins import *

from PySide.QtGui import *
from PySide.QtCore import *

import math

class QHueCircleWidget(QGraphicsView):
    PRESS_NONE = 0
    PRESS_BOX = 1
    PRESS_CIRCLE = 2

    colorChanged = Signal(str)

    def __init__(self, parent):
        super(QHueCircleWidget, self).__init__(parent)
        self.scene = QGraphicsScene(self)
        self.setScene(self.scene)
        self.rectF = None
        self.press_mode = self.PRESS_NONE
        self.color = QColor()
        self.color.setHsv(0, 255, 255, 255)
        self.setColor(self.color)
        self.bg_brush = QBrush(self.create_bg_pixmap())

        # self.setFixedSize(200,200)
        self.setSizePolicy(QSizePolicy.Fixed, QSizePolicy.Fixed)
        self.setSizePolicy(QSizePolicy.Minimum, QSizePolicy.Minimum)
        self.setMinimumSize(200, 200)


    def drawBackground(self, painter, rect):
        """
        :type rect: QRectF
        :type painter: QPainter
        """
        painter.save()

        painter.translate(rect.center())
        painter.setRenderHint(QPainter.Antialiasing, True)
        self.rectF = rect
        self.rectToParam()
        painter.setPen(QPen(Qt.black, 1))
        # draw select color
        painter.setBrush(self.bg_brush)
        painter.drawEllipse(-self.half_width, -self.half_height, self.width / 8, self.height / 8)
        painter.setBrush(self.color)
        painter.drawEllipse(-self.half_width, -self.half_height, self.width / 8, self.height / 8)
        # hue color circle
        painter.setBrush(self.bg_brush)
        painter.drawEllipse(0 - self.half_width, 0 - self.half_height, self.width, self.height)
        color = QColor()
        gradient = QConicalGradient(0, 0, 0)
        for _ in range(11):
            color.setHsv((10 - _) * 36, 255, 255, self.color.alpha())
            gradient.setColorAt(0.1 * _, color)
        painter.setBrush(gradient)
        painter.drawEllipse(0 - self.half_width, 0 - self.half_height, self.width, self.height)
        # center delete circle
        mini_circle_width = self.width * 3 / 4
        mini_circle_height = self.height * 3 / 4
        painter.setBrush(QPalette().brush(QPalette.Midlight))
        painter.drawEllipse(0 - mini_circle_width / 2, 0 - mini_circle_height / 2 , mini_circle_width, mini_circle_height)
        # center box saturation
        gradient = QLinearGradient(-self.quarter_width, 0, self.quarter_width, 0)
        color.setHsv(self.color.hue(), 0, 255, 255)
        gradient.setColorAt(0.0, color)
        color.setHsv(self.color.hue(), 255, 255, 255)
        gradient.setColorAt(1.0, color)
        painter.setBrush(gradient)
        painter.drawRect(-self.quarter_width, -self.quarter_height, self.half_width, self.half_height)

        painter.restore()

    def drawForeground(self, painter, rect):
        """
        :type rect: QRectF
        :type painter: QPainter
        """
        painter.save()

        painter.translate(rect.center())
        painter.setRenderHint(QPainter.Antialiasing, True)
        # center box value
        gradient = QLinearGradient(0, -self.quarter_height, 0, self.quarter_height)
        color = QColor()
        color.setHsv(0, 0, 0, 0)
        gradient.setColorAt(0.0, color)
        color.setHsv(0, 0, 0, 255)
        gradient.setColorAt(1.0, color)
        painter.setBrush(gradient)
        painter.drawRect(-self.quarter_width, -self.quarter_height, self.half_width, self.half_height)
        # lupe for Saturation / Value
        painter.setPen(QPen(QColor(255, 255, 255, 255), 1))
        painter.drawEllipse(self.sv_x - 3, self.sv_y - 3, 7, 7)
        painter.setPen(QPen(QColor(0, 0, 0, 255), 1))
        painter.drawEllipse(self.sv_x - 2, self.sv_y - 2, 5, 5)
        # lupe for Hue
        painter.setPen(QPen(QColor(0, 0, 0, 255), 1))
        painter.setBrush(QColor(255, 255, 255, 0))
        painter.rotate(self.color.hue())
        painter.drawRect(self.width * 3 / 8, -4, self.width / 8, 8)

        painter.restore()

    def mouseMoveEvent(self, event):
        self.clickToColor(event)

    def mousePressEvent(self, event):
        if event.button() == Qt.LeftButton:
            self.rectToParam()
            if self.hitBox(event.x(), event.y()):
                self.press_mode = self.PRESS_BOX
                self.clickToColor(event)
            elif self.hitCircle(event.x(), event.y()):
                self.press_mode = self.PRESS_CIRCLE
                self.clickToColor(event)
            else:
                self.press_mode = self.PRESS_NONE

    def clickToColor(self, event):
        if self.press_mode == self.PRESS_BOX:
            self.clickToBox(event)
        elif self.press_mode == self.PRESS_CIRCLE:
            self.clickCircle(event)

        self.colorChanged.emit('colorChanged')
        self.scene.update()

    def hitBox(self, x, y):
        rect = QRect(self.quarter_width, self.quarter_height, self.width * 2 / 4, self.height * 2 / 4)
        return rect.contains(x, y)

    def hitCircle(self, x, y):
        path = QPainterPath()
        path.addEllipse(0, 0, self.width, self.height)

        path2 = QPainterPath()
        path2.addEllipse(self.quarter_width / 2., self.quarter_height / 2., self.width / 4. * 3., self.height / 4. * 3.)

        pos = QPointF(x, y)
        return path.contains(pos) and not path2.contains(pos)

    def clickToBox(self, event):
        if not self.hitBox(event.x(), event.y()):
            return

        x = event.x()
        y = event.y()

        col_sat = 255 * (x - self.quarter_width) / self.half_width
        col_sat = 0 if col_sat < 0 else col_sat
        col_sat = 255 if col_sat > 255 else col_sat

        col_val = 255 * (self.half_height - (y - self.quarter_height)) / self.half_height
        col_val = 0 if col_val < 0 else col_val
        col_val = 255 if col_val > 255 else col_val

        self.color.setHsv(
            self.color.hue(),
            col_sat,
            col_val,
            self.color.alpha()
        )
        self.sv_x = x - self.half_width
        self.sv_y = y - self.half_height

    def clickCircle(self, event):
        x = event.x()
        y = event.y()

        k = int(math.degrees(math.atan2(x - self.half_width, self.half_height - y)))
        self.color.setHsv(
            (k - 90) % 360,
            self.color.saturation(),
            self.color.value(),
            self.color.alpha()
        )
        self.hue_x = x - self.half_width
        self.hue_y = y - self.half_height

    def getColor(self):
        return(self.color)

    def setColor(self, color):
        self.color = QColor(color)
        if self.rectF == None:
            self.sv_x = 0
            self.sv_y = 0
            self.hue_x = 0
            self.hue_y = 0
            self.scene.update()
        else:
            self.rectToParam()
            # SV
            self.sv_x = color.saturation() * self.half_width / 255 - self.quarter_width
            self.sv_y = (255 - color.value()) * self.half_height / 255 - self.quarter_height
            # Hue
            radian = ((color.hue()) % 360) * math.pi / 180
            self.hue_x = math.cos(radian) * self.half_width
            self.hue_y = math.sin(radian) * self.half_height
        self.scene.update()

    def rectToParam(self):
        if self.rectF == None:
            rect = QRectF(0, 0, 200, 200)
        else:
            rect = self.rectF

        self.width = rect.toRect().width()
        self.half_width = self.width / 2
        self.quarter_width = self.width / 4

        self.height = rect.toRect().height()
        self.half_height = self.height / 2
        self.quarter_height = self.height / 4

    @staticmethod
    def create_bg_pixmap(color1=None, color2=None):
        """
        :rtype: QPixmap
        """
        pixmap = QPixmap(QSize(16, 16))
        color1 = color1 or QColor(128, 128, 128)
        color2 = color2 or QColor(168, 168, 168)

        painter = QPainter(pixmap)
        painter.save()
        brush1 = QBrush(color1)
        brush2 = QBrush(color2)
        painter.fillRect(0, 0, 8, 8, brush1)
        painter.fillRect(8, 8, 8, 8, brush1)
        painter.fillRect(8, 0, 8, 8, brush2)
        painter.fillRect(0, 8, 8, 8, brush2)
        painter.restore()
        painter.end()

        return pixmap

sample.py


from __future__ import division, print_function, unicode_literals, absolute_import

from PySide.QtGui import *
from PySide.QtCore import *
import sys

class MainWindow(QMainWindow):
    def __init__(self, parent=None):
        super(MainWindow, self).__init__(parent)
        self.resize(700, 500)

        self.colorCircle1 = QHueCircleWidget(self)

        self.colorCircle2 = QHueCircleWidget(self)
        self.colorCircle2.resize(400, 400)
        self.colorCircle2.move(260, 50)

        # alpha color sample
        color = QColor(255, 0, 0, 100)
        self.colorCircle1.setColor(color)
        self.colorCircle2.setColor(color)

        self.colorCircle1.colorChanged.connect(self.onUpdateColor1)
        self.colorCircle2.colorChanged.connect(self.onUpdateColor2)

    @Slot()
    def onUpdateColor1(self):
        color = self.colorCircle1.getColor()
        self.colorCircle2.setColor(color)

    @Slot()
    def onUpdateColor2(self):
        color = self.colorCircle2.getColor()
        self.colorCircle1.setColor(color)

def main():
    app = QApplication(sys.argv)
    main_window = MainWindow()
    main_window.show()
    sys.exit(app.exec_())

if __name__ == "__main__":
    main()

Recommended Posts

Créez un sélecteur de couleurs pour la roue chromatique avec Python + Qt (PySide)
Créer une barre de couleurs avec Python + Qt (PySide)
Créer un widget avec une couleur spécifiée avec Python + Qt (PySide)
Créez un Twitter BOT avec le SDK GoogleAppEngine pour Python
Créer un LINE BOT avec Minette pour Python
Remplissez l'arrière-plan d'une seule couleur avec OpenCV2 + Python
Créer une couche pour AWS Lambda Python dans Docker
Créer un répertoire avec python
Créer un compte enfant de connect with Stripe en Python
[Python] Créer un écran pour le code d'état HTTP 403/404/500 avec Django
Créez un environnement virtuel avec Python!
Créez une illusion rayée avec correction gamma pour Python3 et openCV3
L'histoire de la création d'un pilote standard pour db avec python.
Créer un Ubuntu de démarrage USB avec un environnement Python pour l'analyse des données
Créez un programme de jugement de compatibilité avec le module aléatoire de python.
Créer un décorateur de fonction Python avec Class
Créez une image factice avec Python + PIL.
Créons un environnement virtuel pour Python
[Python] Créez un environnement virtuel avec Anaconda
Créons un groupe gratuit avec Python
Rechercher le labyrinthe avec l'algorithme python A *
Qt pour l'application de bureau de l'application Python
Créer un compteur de fréquence de mots avec Python 3.4
[Introduction à Udemy Python3 + Application] 47. Traitez le dictionnaire avec une instruction for
Créer un enregistrement avec des pièces jointes dans KINTONE à l'aide du module de requêtes Python
[Python] Récupérez les fichiers dans le dossier avec Python
Création d'un wrapper Python pour l'API Qiita
Obtenez un billet pour un parc à thème avec python
Utilisez Logger avec Python pour le moment
Procédure de création d'un LineBot réalisé avec Python
Créer une page qui se charge indéfiniment avec python
[Note] Créez une classe de fuseau horaire sur une ligne avec python
Vous pouvez facilement créer une interface graphique même avec Python
Créer un environnement de construction python3 avec Sublime Text3
Créez un tableau de bord pour les appareils réseau avec Django!
Python: préparez un sérialiseur pour l'instance de classe:
Étapes pour créer un bot Twitter avec Python
Commandes pour créer un environnement python3 avec virtualenv
Créer un arbre de décision à partir de 0 avec Python (1. Présentation)
Créer une nouvelle page en confluence avec Python
Créer un fichier au format Photoshop (.psd) avec python
Facile à créer une application console Python avec Click
Créez un outil de traduction avec Translate Toolkit
Créons un système de réception simple avec le framework sans serveur Python Chalice et Twilio
Transformez plusieurs listes avec l'instruction for en même temps en Python
[Introduction à Python] Comment obtenir l'index des données avec l'instruction for
Créez une base de données propre pour les tests avec FastAPI et effectuez le test Unittest de l'API avec pytest
Automatisez la suppression de l'arrière-plan pour les derniers portraits dans un répertoire avec Python et API
Créer un module Python
Exécutez avec CentOS7 + Apache2.4 + Python3.6 pour le moment
Comment créer un sous-menu avec le plug-in [Blender]
[CRUD] [Django] Créer un site CRUD en utilisant le framework Python Django ~ 1 ~
[Python] 2 Créez une carte risque-rendement pour votre portefeuille d'actifs
Créez un environnement python pour chaque répertoire avec pyenv-virtualenv
[Python] Générer ValueObject avec un constructeur complet à l'aide de classes de données
Essayez de créer une application Todo avec le framework Django REST
Pourquoi ne pas créer facilement une table élégante avec Python?
Créez un environnement de développement python avec vagrant + ansible + fabric
Faire un point d'arrêt sur la couche c avec python