PySideのQColorDialogの外観が普通なので、自分でカラーピッカーのWidgetを作成しました。ここではカラーバーについて紹介します。
Python歴3ヶ月の私でもそれっぽいものが作れるのが、Python&Qtのいいところです。
ソースをGitHubに登録しました。
https://github.com/tokyo-noctambulist/colorpicker.git
(2017/03/07 更新)
色指定時に、値を参照渡していたのをcopyに変更
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()