LoginSignup
5
1

More than 5 years have passed since last update.

Python+Qt(PySide)でカラーバーを作成

Last updated at Posted at 2017-02-07

 PySideのQColorDialogの外観が普通なので、自分でカラーピッカーのWidgetを作成しました。ここではカラーバーについて紹介します。
 Python歴3ヶ月の私でもそれっぽいものが作れるのが、Python&Qtのいいところです。

 ソースをGitHubに登録しました。
https://github.com/tokyo-noctambulist/colorpicker.git

(2017/03/07 更新)
  色指定時に、値を参照渡していたのをcopyに変更

サンプル

image

 sample.pyでは、2つの色相のカラーバーを連動させて、別に透明度のカラーバーを表示しています。


カラーバーの種類

 カラーバーの種類を、色相、彩度、明度、透明度から選択できます。
 PyPIに登録しました。pip等でinstallできます。

種類
色相 BAR_TYPE_HUE = 0
彩度 BAR_TYPE_SATURATION = 1
明度 BAR_TYPE_VALUE = 2
透明度 BAR_TYPE_ALPHA = 3
function
pip install colorpicker #install

from colorpicker import *

QColorBarWidget(, BARの種類(=未指定の時は色相))

widget = QColorBarWidget(self, BAR_TYPE_VALUE)
widget.setColor(QColor(0,0,0,0)) #色をセット
color = widget.getColor() #色を収得
colorBar.colorChanged.connect(onUpdateColor) # signal-slot

 PhotoshopやPainterのように複数のカラーピッカーを表示して、色を連動させる場合は、colorChangedのsignal()で色の変更を受け取って、他のWidgetと連動させてください。


QColorBarWidget.py
from __future__ import division, print_function, unicode_literals, absolute_import

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

# TYPE
BAR_TYPE_HUE = 0
BAR_TYPE_SATURATION = 1
BAR_TYPE_VALUE = 2
BAR_TYPE_ALPHA = 3
BAR_TYPE_MAX = 4

Lupe_Color = [
    QColor(0, 0, 0, 255),
    QColor(0, 0, 0, 255),
    QColor(255, 255, 255, 255),
    QColor(255, 0, 0, 255)
]


class QColorBarWidget(QGraphicsView):
    colorChanged = Signal(str)

    def __init__(self, parent, type=BAR_TYPE_HUE):
        super(QColorBarWidget, self).__init__(parent)
        self.scene = QGraphicsScene(self)
        self.setScene(self.scene)
        self.width = 0

        self.type = type if type < BAR_TYPE_MAX else BAR_TYPE_HUE
        self.lupe_color = Lupe_Color[type]

        self.color = QColor()
        self.color.setHsv(0, 255, 255, 255)
        self.setColor(self.color)

        # BG
        pixmap = QPixmap(QSize(16, 16))
        tile = QPainter(pixmap)
        tile.save()
        brush1 = QBrush(QColor(128, 128, 128))
        brush2 = QBrush(QColor(168, 168, 168))
        tile.fillRect(0, 0, 8, 8, brush1)
        tile.fillRect(8, 8, 8, 8, brush1)
        tile.fillRect(8, 0, 8, 8, brush2)
        tile.fillRect(0, 8, 8, 8, brush2)
        tile.restore()
        tile.end()
        self.bg_brush = QBrush(pixmap)

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

    def drawForeground(self, painter, rect):
        """
        :type rect: QRectF
        :type painter: QPainter
        """
        painter.save()
        painter.translate(rect.center())
        painter.setRenderHint(QPainter.Antialiasing, True)
        self.width = rect.toRect().width()
        half_width = self.width / 2
        height = rect.toRect().height()
        half_height = height / 2
        # bar
        gradient = QLinearGradient(-half_width, 0, half_width, 0)
        self.makeGradient(gradient)
        painter.setBrush(gradient)
        painter.drawRect(-half_width, -half_height, self.width, height)
        # lupe
        painter.setPen(QPen(self.lupe_color, 1))
        painter.setBrush(QColor(0, 0, 0, 0))
        half_width = self.px - half_width
        painter.drawEllipse(half_width - 2, 2 - half_height, 5, 5)
        painter.fillRect(half_width, 6 - half_height, 1, height, QBrush(self.lupe_color))

        painter.restore()

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

    def mousePressEvent(self, event):
        if event.button() == Qt.LeftButton:
            self.clickToColor(event)

    def clickToColor(self, event):
        self.px = event.pos().x()
        param = self.px / self.width
        param = 0 if param < 0 else param
        if self.type == BAR_TYPE_HUE:
            self.color.setHsv(360 * param, self.color.saturation(), self.color.value(), self.color.alpha())
        elif self.type == BAR_TYPE_SATURATION:
            self.color.setHsv(self.color.hue(), 255 * param, self.color.value(), self.color.alpha())
        elif self.type == BAR_TYPE_VALUE:
            self.color.setHsv(self.color.hue(), self.color.saturation(), 255 * param, self.color.alpha())
        else:  # alpha
            self.color.setAlphaF(param)

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

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

    def setColor(self, color):
        self.color = QColor(color)
        if self.type == BAR_TYPE_HUE:
            self.px = color.hue() * self.width / 360
        elif self.type == BAR_TYPE_SATURATION:
            self.px = color.saturation() * self.width / 255
        elif self.type == BAR_TYPE_VALUE:
            self.px = color.value() * self.width / 255
        else:  # alpha
            self.px = color.alpha() * self.width / 255
        self.scene.update()

    def makeGradient(self, gradient):
        color = QColor()
        if self.type == BAR_TYPE_HUE:
            for _ in range(11):
                color.setHsv(_ * 36, 255, 255, 255)
                gradient.setColorAt(0.1 * _, color)
        elif self.type == BAR_TYPE_SATURATION:
            color.setHsv(360, 0, 255, 255)
            gradient.setColorAt(0.0, color)
            color.setHsv(360, 255, 255, 255)
            gradient.setColorAt(1.0, color)
        elif self.type == BAR_TYPE_VALUE:
            color.setHsv(360, 255, 0, 255)
            gradient.setColorAt(0.0, color)
            color.setHsv(360, 255, 255, 255)
            gradient.setColorAt(1.0, color)
        else:  # alpha
            color.setRgb(255, 255, 255, 0)
            gradient.setColorAt(0.0, color)
            color.setRgb(255, 255, 255, 255)
            gradient.setColorAt(1.0, color)
        return
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(300, 100)

        self.colorBar1 = QColorBarWidget(self)
        self.colorBar1.resize(150, 20)

        self.colorBar2 = QColorBarWidget(self, BAR_TYPE_HUE)
        self.colorBar2.resize(250, 30)
        self.colorBar2.move(0, 30)

        self.colorBar3 = QColorBarWidget(self, BAR_TYPE_ALPHA)
        self.colorBar3.resize(200, 20)
        self.colorBar3.move(50, 70)

        self.colorBar1.colorChanged.connect(self.onUpdateColor1)
        self.colorBar2.colorChanged.connect(self.onUpdateColor2)

    @Slot()
    def onUpdateColor1(self):
        color = self.colorBar1.getColor()
        self.colorBar2.setColor(color)

    @Slot()
    def onUpdateColor2(self):
        color = self.colorBar2.getColor()
        self.colorBar1.setColor(color)

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

if __name__ == "__main__":
    main()

5
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
5
1