#!python # -*- mode: python; coding: utf-8 -*- # Last updated: <2016/11/06 23:11:51 +0900> u""" QSliderとQSpinBoxを1つのWidgetにまとめて並べてみるサンプル. RGB/HSLのQSlider + QSpinBoxを用意して値を連動させる。 かつ、ビットマップ画像をGIMPの「着色」風に変更してみる。 Windows10 x64 + Python 2.7.11 + PySide 1.2.4 """ import sys from PySide.QtCore import * # NOQA from PySide.QtGui import * # NOQA IMG_FILE = "temp.png" class LabelSliderSpinBox(QWidget): """Slider and SpinBox.""" # Signalを用意 valueChanged = Signal(int) def __init__(self, text, parent=None): """init.""" super(LabelSliderSpinBox, self).__init__(parent) # self.setContentsMargins(0, 0, 0, 0) hl = QHBoxLayout() hl.setContentsMargins(0, 0, 0, 0) # hl.setSpacing(0) self.lbl = QLabel(text, self) self.sld = QSlider(Qt.Horizontal, self) self.spb = QSpinBox(self) hl.addWidget(self.lbl) hl.addWidget(self.sld) hl.addWidget(self.spb) self.setLayout(hl) self.sld.valueChanged[int].connect(self.changed_slider_value) self.spb.valueChanged[int].connect(self.changed_spinbox_value) # 用意したシグナルとスロットを関連付ける self.valueChanged[int].connect(self.changedValue) def setText(self, text): """set QLabel text.""" self.lbl.setText(text) def setRange(self, start_v, end_v): """set range QSlider and QSpinBox.""" self.sld.setRange(start_v, end_v) self.spb.setRange(start_v, end_v) def setValue(self, value): """set value to QSlider and QSpinBox.""" self.sld.setValue(value) self.spb.setValue(value) def value(self): """get value.""" return self.spb.value() def changed_slider_value(self, n): """changed slider value.""" self.spb.setValue(n) def changed_spinbox_value(self, n): """changed spinbox value.""" self.sld.setValue(n) self.valueChanged.emit(n) # 値が変わったのでシグナルを発行 # スロットを用意する @Slot(int) def changedValue(self, value): """changed slider or spinbox value.""" pass # print("value = %d" % value) class MyWidget(QWidget): """My Widget.""" def __init__(self, *argv, **keywords): """init.""" super(MyWidget, self).__init__(*argv, **keywords) self.setWindowTitle("Color Slider") self.event_ignore = False l = QVBoxLayout() # bitmap display label im = QImage(IMG_FILE) lbl = QLabel("", self) lbl.setPixmap(QPixmap.fromImage(im)) l.addWidget(lbl) self.im = im self.lbl = lbl self.lum_im = self.make_lum_image(im) # color display button btn = QPushButton() btn.setFixedSize(32, 32) # set button background-color btn.setStyleSheet("QWidget { background-color: %s }" % QColor(128, 128, 128).name()) l.addWidget(btn) btn.clicked.connect(self.show_color_dialog) self.btn = btn # sliders data = [ ("R", 0, 255, 128), ("G", 0, 255, 128), ("B", 0, 255, 128), ("H", 0, 360, 180), ("S", 0, 255, 128), ("L", 0, 255, 128)] self.sliders = [] for (i, d) in enumerate(data): text, start_v, end_v, init_v = d w = LabelSliderSpinBox(text, self) w.setRange(start_v, end_v) w.setValue(init_v) l.addWidget(w) self.sliders.append(w) if i < 3: w.valueChanged.connect(self.changed_rgb) else: w.valueChanged.connect(self.changed_hsl) self.setLayout(l) def update_rgb_disp(self, col): """update RGB disp button.""" # set background-color self.btn.setStyleSheet("QWidget { background-color: %s }" % col.name()) def set_sliders_rgb(self, col): """set RGB slider value.""" r, g, b = col.red(), col.green(), col.blue() self.set_sliders(0, (r, g, b)) def set_sliders_hsl(self, col): """set HSL slider value.""" h, s, l = col.hslHue(), col.hslSaturation(), col.lightness() self.set_sliders(3, (h, s, l)) def set_sliders(self, idx, v): """set 3 slider value.""" for i in range(3): if self.sliders[idx + i].value() != v[i]: self.sliders[idx + i].setValue(v[i]) def get_sliders(self, idx): """get 3 slider value.""" v = [] for i in range(3): v.append(self.sliders[idx + i].value()) return tuple(v) def changed_rgb(self, _): """changed RGB value.""" if not self.event_ignore: self.event_ignore = True r, g, b = self.get_sliders(0) col = QColor(r, g, b) self.set_sliders_hsl(col) self.update_rgb_disp(col) self.change_pixmap_color(self.lum_im) self.event_ignore = False def changed_hsl(self, _): """changed HSL value.""" if not self.event_ignore: self.event_ignore = True h, s, l = self.get_sliders(3) col = QColor() col.setHsl(h, s, l) self.set_sliders_rgb(col) self.update_rgb_disp(col) self.change_pixmap_color(self.lum_im) self.event_ignore = False def show_color_dialog(self): """open QColorDialog.""" col = QColorDialog.getColor() if col.isValid(): self.set_sliders_rgb(col) def make_lum_image(self, im): """make luminance image.""" w, h = im.size().width(), im.size().height() dst = [] for y in range(h): d = [] for x in range(w): c = im.pixel(x, y) r, g, b = qRed(c), qGreen(c), qBlue(c) # get luminance l = int(0.2126 * r + 0.7152 * g + 0.0722 * b) l = max(0, min(l, 255)) d.append((l, qAlpha(c))) dst.append(d) return dst def change_pixmap_color(self, src): """change QPixmap color.""" b_h, b_s, b_l = self.get_sliders(3) w, h = len(src), len(src[0]) dst = QImage(w, h, QImage.Format_ARGB32) c2 = QColor() for y in range(h): for x in range(w): l, a = src[y][x] if b_l > 128: l *= (255.0 - b_l) / 127.0 l += (255.0 - ((255 - b_l) * 255.0 / 127.0)) elif b_l < 128: l *= b_l / 128.0 l = int(l) if l < 0: l = 0 if l > 255: l = 255 c2.setHsl(b_h, b_s, l, a) dst.setPixel(x, y, c2.rgba()) self.lbl.setPixmap(QPixmap.fromImage(dst)) def main(): """Main.""" app = QApplication(sys.argv) w = MyWidget() w.show() sys.exit(app.exec_()) if __name__ == '__main__': main()