Только цветовой градиент из Qt5 ColorDialog

Я хотел спросить, можно ли использовать только часть "Градиент цвета" (обведена красным) QColorDialog.

QColorDialog

Я использую PyQt5 и Python3 на разных машинах Linux (ubuntu + raspian).

3 ответа

Решение

Нужно только скрыть все элементы, кроме QColorPicker а также QColorLuminancePicker.

import sys

from PyQt5 import QtCore, QtGui, QtWidgets


class ColorDialog(QtWidgets.QColorDialog):
    def __init__(self, parent=None):
        super().__init__(parent)
        self.setOptions(self.options() | QtWidgets.QColorDialog.DontUseNativeDialog)

        for children in self.findChildren(QtWidgets.QWidget):
            classname = children.metaObject().className()
            if classname not in ("QColorPicker", "QColorLuminancePicker"):
                children.hide()


if __name__ == "__main__":
    app = QtWidgets.QApplication(sys.argv)

    colordialog = ColorDialog()
    label = QtWidgets.QLabel(alignment=QtCore.Qt.AlignCenter)

    def onCurrentColorChanged(color):
        label.setStyleSheet("background-color: {}".format(color.name()))

    colordialog.currentColorChanged.connect(onCurrentColorChanged)
    onCurrentColorChanged(colordialog.currentColor())

    w = QtWidgets.QWidget()
    lay = QtWidgets.QVBoxLayout(w)
    lay.addWidget(colordialog, alignment=QtCore.Qt.AlignCenter)
    lay.addWidget(label)
    w.show()

    sys.exit(app.exec_())

ht tps:https://stackru.com/images/c1f6ce89e8724a2368fdc0ceededf326fce19d06.png

Вы можете проверить этот дизайн круговой палитры цветов для PyQt

PyQt Круглый Color Picker

Это выглядит так и может быть легко изменено

Решение, предложенное eyllanesc совершенна (и умный) как всегда.

Тем не менее, несколько месяцев назад мне пришлось реализовать свой собственный виджет выбора цвета, который создает виджет "цветная радуга" только из кода, и я хотел бы поделиться частью этого кода, поскольку я считаю, что он может представлять некоторый интерес, особенно в отношении создание "радуги" и определение цвета.
Я отредактировал его, чтобы сделать его простым и удобным виджетом для выбора цвета.

from PyQt5 import QtCore, QtGui, QtWidgets

# a helper function that ensures that a value is between the given range
sanitize = lambda m, value, M: min(max(m, value), M)

class RgbPicker(QtWidgets.QLabel):
    colorGrads = QtGui.QLinearGradient(0, 0, 1, 0)
    colorGrads.setCoordinateMode(colorGrads.ObjectBoundingMode)
    xRatio = 1. / 6
    # the basic "rainbow" gradient
    colorGrads.setColorAt(0, QtCore.Qt.red)
    colorGrads.setColorAt(1, QtCore.Qt.red)
    colorGrads.setColorAt(xRatio, QtCore.Qt.magenta)
    colorGrads.setColorAt(xRatio * 2, QtCore.Qt.blue)
    colorGrads.setColorAt(xRatio * 3, QtCore.Qt.cyan)
    colorGrads.setColorAt(xRatio * 4, QtCore.Qt.green)
    colorGrads.setColorAt(xRatio * 5, QtCore.Qt.yellow)

    # the superimposed white component
    maskGrad = QtGui.QLinearGradient(0, 0, 0, 1)
    maskGrad.setCoordinateMode(maskGrad.ObjectBoundingMode)
    maskGrad.setColorAt(0, QtCore.Qt.transparent)
    maskGrad.setColorAt(1, QtCore.Qt.white)

    # the pseudo arrow cursor
    cursorPath = QtGui.QPainterPath()
    cursorPath.moveTo(-10, 0)
    cursorPath.lineTo(-4, 0)
    cursorPath.moveTo(0, -10)
    cursorPath.lineTo(0, -4)
    cursorPath.moveTo(4, 0)
    cursorPath.lineTo(10, 0)
    cursorPath.moveTo(0, 4)
    cursorPath.lineTo(0, 10)
    cursorPen = QtGui.QPen(QtCore.Qt.black, 3)

    colorChanged = QtCore.pyqtSignal(QtGui.QColor)

    def __init__(self, color=None):
        QtWidgets.QLabel.__init__(self)
        self.setFocusPolicy(QtCore.Qt.StrongFocus)
        self.setFixedSize(220, 200)
        # create a pixmap that shows the "rainbow" and draw its contents
        pixmap = QtGui.QPixmap(self.size())
        qp = QtGui.QPainter(pixmap)
        qp.fillRect(pixmap.rect(), self.colorGrads)
        qp.fillRect(pixmap.rect(), self.maskGrad)
        qp.end()
        self.setPixmap(pixmap)
        self.image = pixmap.toImage()

        # a multiplier, used when an arrow key is kept pressed
        self.keyTimer = QtCore.QTimer()
        self.keyTimer.setInterval(1000)
        self.keyTimer.timeout.connect(lambda: setattr(self, 'keyMulti', self.keyMulti + 1))

        self._cursorPos = QtCore.QPoint()
        self._color = color

        self.setColor(color)

    @property
    def color(self):
        return self._color

    @property
    def cursorPos(self):
        return self._cursorPos

    @cursorPos.setter
    def cursorPos(self, pos):
        self._cursorPos = pos
        self.update()

    def sanitizePos(self, pos):
        # sanitize the position within the color rainbow margins
        return QtCore.QPoint(sanitize(0, pos.x(), self.width() - 1), sanitize(0, pos.y(), self.height() - 1))

    def setColor(self, color):
        h, s, v, a = color.getHsv()
        # compute the coordinates based on hsv components
        x = (360 - h) * (self.width() - 1) / 360.
        y = (255 - s) * (self.height() - 1) / 255.
        self.cursorPos = QtCore.QPoint(x, y)

    def translateColorCursor(self, pos):
        # return the color of the given pixel
        return QtGui.QColor(self.image.pixel(pos))

    def mousePressEvent(self, event):
        pos = self.sanitizePos(event.pos())
        self._color = self.translateColorCursor(pos)
        self.colorChanged.emit(QtGui.QColor(self._color))
        self.cursorPos = pos

    def mouseMoveEvent(self, event):
        pos = self.sanitizePos(event.pos())
        self._color = self.translateColorCursor(pos)
        self.colorChanged.emit(QtGui.QColor(self._color))
        self.cursorPos = pos

    def keyPressEvent(self, event):
        deltaX = deltaY = 0
        # emulation of the Qt internal color picker keyboard navigation
        if event.modifiers() & QtCore.Qt.KeypadModifier:
            if event.key() in (QtCore.Qt.Key_7, QtCore.Qt.Key_Home):
                deltaX = deltaY = -1
            elif event.key() in (QtCore.Qt.Key_8, QtCore.Qt.Key_Up):
                deltaY = -1
            elif event.key() in (QtCore.Qt.Key_9, QtCore.Qt.Key_PageUp):
                deltaX = 1
                deltaY = -1
            elif event.key() in (QtCore.Qt.Key_4, QtCore.Qt.Key_Left):
                deltaX = -1
            elif event.key() in (QtCore.Qt.Key_6, QtCore.Qt.Key_Right):
                deltaX = 1
            elif event.key() in (QtCore.Qt.Key_1, QtCore.Qt.Key_End):
                deltaX = -1
                deltaY = 1
            elif event.key() in (QtCore.Qt.Key_2, QtCore.Qt.Key_Down):
                deltaY = 1
            elif event.key() in (QtCore.Qt.Key_3, QtCore.Qt.Key_PageDown):
                deltaX = deltaY = 1
        elif event.key() == QtCore.Qt.Key_Left:
            deltaX = -1
        elif event.key() == QtCore.Qt.Key_Right:
            deltaX = 1
        elif event.key() == QtCore.Qt.Key_Up:
            deltaY = -1
        elif event.key() == QtCore.Qt.Key_Down:
            deltaY = 1
        elif event.key() == QtCore.Qt.Key_Home:
            if event.modifiers() == QtCore.Qt.ShiftModifier:
                deltaY = -1000
            elif event.modifiers() == QtCore.Qt.ControlModifier:
                deltaX = deltaY = -1000
            else:
                deltaX = -1000
        elif event.key() == QtCore.Qt.Key_End:
            if event.modifiers() == QtCore.Qt.ShiftModifier:
                deltaY = 1000
            elif event.modifiers() == QtCore.Qt.ControlModifier:
                deltaX = deltaY = 1000
            else:
                deltaX = 1000
        elif event.key() == QtCore.Qt.Key_PageUp and not event.modifiers() & QtCore.Qt.KeypadModifier:
            deltaY = -10
        elif event.key() == QtCore.Qt.Key_PageDown and not event.modifiers() & QtCore.Qt.KeypadModifier:
            deltaY = +10
        else:
            return QtWidgets.QWidget.keyPressEvent(self, event)
        if not event.isAutoRepeat():
            self.keyTimer.start()
            self.keyMulti = 1
        if deltaX or deltaY:
            multi = self.keyMulti
            if event.modifiers() & QtCore.Qt.ShiftModifier:
                multi *= 10
            deltaX *= multi
            deltaY *= multi
        pos = self.sanitizePos(QtCore.QPoint(self.cursorPos.x() + deltaX, self.cursorPos.y() + deltaY))
        self._color = self.translateColorCursor(pos)
        self.colorChanged.emit(QtGui.QColor(self._color))
        self.cursorPos = pos

    def keyReleaseEvent(self, event):
        if not event.isAutoRepeat():
            self.keyTimer.stop()
        QtWidgets.QWidget.keyReleaseEvent(self, event)

    def paintEvent(self, event):
        QtWidgets.QLabel.paintEvent(self, event)
        qp = QtGui.QPainter(self)
        qp.setPen(self.cursorPen)
        # translate to the crosshair position and paint it
        qp.translate(self.cursorPos)
        qp.drawPath(self.cursorPath)


class BlackPicker(QtWidgets.QWidget):
    # the "black" selector, which has a gradient based on the current selected
    # color of the RgbPicker (selected color -> black)

    _rect = QtCore.QRect(0, 8, 16, 200)

    grad = QtGui.QLinearGradient(0, 0, 0, 1)
    grad.setCoordinateMode(grad.ObjectBoundingMode)
    grad.setColorAt(1, QtCore.Qt.black)

    arrow = QtGui.QPainterPath()
    arrow.lineTo(4, -4)
    arrow.lineTo(4, 4)
    arrow.closeSubpath()
    _color = QtGui.QColor()
    _black = -1

    blackChanged = QtCore.pyqtSignal(float)

    def __init__(self, color):
        QtWidgets.QWidget.__init__(self)
        self.color = QtGui.QColor(color)
        self.setFixedSize(22, 216)

    @property
    def black(self):
        return self._black

    @black.setter
    def black(self, black):
        if black == self._black:
            return
        self._black = black
        self.update()
        self.blackChanged.emit(black)

    @property
    def color(self):
        return self._color

    @color.setter
    def color(self, color):
        if color == self._color:
            return
        self._color = QtGui.QColor(color)
        self.grad.setColorAt(0, color)
        self.black = color.getCmykF()[3]

    def setWhiteColor(self, color):
        self.grad.setColorAt(0, color)
        self.update()

    def setColor(self, color):
        self.color = color

    def mousePressEvent(self, event):
        self.black = sanitize(0, event.pos().y() - self._rect.top(), 
            self._rect.height()) / 200.

    def mouseMoveEvent(self, event):
        self.black = sanitize(0, event.pos().y() - self._rect.top(), 
            self._rect.height()) / 200.

    def wheelEvent(self, event):
        if event.pixelDelta().y() < 0:
            delta = .01
        else:
            delta = -.01
        self.black = sanitize(0, self.black + delta, 1)

    def paintEvent(self, event):
        qp = QtGui.QPainter(self)
        qp.setRenderHints(qp.Antialiasing)
        qp.fillRect(self._rect, self.grad)
        qp.translate(self._rect.right() + 2, self._rect.top() + self.black * self._rect.height())
        qp.setBrush(QtCore.Qt.black)
        qp.translate(.5, .5)
        qp.drawPath(self.arrow)


class ColorPicker(QtWidgets.QWidget):
    colorChanged = QtCore.pyqtSignal(QtGui.QColor)

    def __init__(self, color=None, parent=None):
        super().__init__(parent)
        layout = QtWidgets.QGridLayout(self)

        if not (isinstance(color, QtGui.QColor) and color.isValid()):
            if isinstance(color, QtCore.Qt.GlobalColor):
                color = QtGui.QColor(color)
            else:
                color = self.palette().color(QtGui.QPalette.WindowText)

        self.rgbPicker = RgbPicker(color)
        layout.addWidget(self.rgbPicker, 0, 0)

        self.blackPicker = BlackPicker(color)
        layout.addWidget(self.blackPicker, 0, 1)

        self.colorWidget = QtWidgets.QWidget()
        layout.addWidget(self.colorWidget, 1, 0, 1, 2)
        self.colorWidget.setMinimumHeight(16)
        self.colorWidget.setAutoFillBackground(True)

        self.colorLabel = QtWidgets.QLabel()
        layout.addWidget(self.colorLabel)

        self.rgbPicker.colorChanged.connect(self.updateColor)
        self.rgbPicker.colorChanged.connect(self.blackPicker.setWhiteColor)
        self.blackPicker.blackChanged.connect(self.updateColor)

        self.updateColor()

    def updateColor(self):
        color = self.rgbPicker.color
        c, m, y, _, _ = color.getCmykF()
        color.setCmykF(c, m, y, self.blackPicker.black)
        palette = self.colorWidget.palette()
        palette.setColor(palette.Window, color)
        self.colorWidget.setPalette(palette)
        r, g, b = color.getRgb()[:-1]
        hexColor = '{:02X}{:02X}{:02X}'.format(r, g, b)
        self.colorLabel.setText('R:{:03} G:{:03} B:{:03} - #{}'.format(
            r, g, b, hexColor))
        self.colorChanged.emit(color)


if __name__ == '__main__':
    import sys
    app = QtWidgets.QApplication(sys.argv)
    picker = ColorPicker(QtGui.QColor(QtCore.Qt.white))
    picker.show()
    sys.exit(app.exec())
Другие вопросы по тегам