仅Qt5 ColorDialog中的颜色渐变

问题描述 投票:2回答:2

我想问问是否可以仅使用QColorDialog的Color Gradient(红色包围)部分。

“

我正在不同的Linux机器(ubuntu + raspian)上使用PyQt5和Python3。

python python-3.x pyqt pyqt5 qcolordialog
2个回答
2
投票

仅需隐藏QColorPickerQColorLuminancePicker以外的所有元素。

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_())

enter image description here


0
投票

solution proposed by eyllanesc一如既往的完美(而且很聪明)。>>

尽管如此,几个月前,我不得不实现自己的颜色选择器小部件,该小部件仅通过代码创建了“颜色彩虹”小部件,我想分享其中的一部分代码,因为我认为这可能会引起人们的兴趣,特别是关于“彩虹”的创建和颜色检测。我已经对其进行了编辑,使其成为基本的“颜色选择器”小部件。

screenshot of the "fake" color picker widget

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())
© www.soinside.com 2019 - 2024. All rights reserved.