You can do this fairly easily using a QWidgetAction.
The example code below uses tool-buttons with icons for the grid of colors, but there are many other widgets could just as easily be be used. The palette
method can be reimplemented if you need a different set of colors.
class ColorAction(QtGui.QWidgetAction):
colorSelected = QtCore.pyqtSignal(QtGui.QColor)
def __init__(self, parent):
QtGui.QWidgetAction.__init__(self, parent)
widget = QtGui.QWidget(parent)
layout = QtGui.QGridLayout(widget)
layout.setSpacing(0)
layout.setContentsMargins(2, 2, 2, 2)
palette = self.palette()
count = len(palette)
rows = count // round(count ** .5)
for row in range(rows):
for column in range(count // rows):
color = palette.pop()
button = QtGui.QToolButton(widget)
button.setAutoRaise(True)
button.clicked[()].connect(
lambda color=color: self.handleButton(color))
pixmap = QtGui.QPixmap(16, 16)
pixmap.fill(color)
button.setIcon(QtGui.QIcon(pixmap))
layout.addWidget(button, row, column)
self.setDefaultWidget(widget)
def handleButton(self, color):
self.parent().hide()
self.colorSelected.emit(color)
def palette(self):
palette = []
for g in range(4):
for r in range(4):
for b in range(3):
palette.append(QtGui.QColor(
r * 255 // 3, g * 255 // 3, b * 255 // 2))
return palette
class ColorMenu(QtGui.QMenu):
def __init__(self, parent):
QtGui.QMenu.__init__(self, parent)
self.colorAction = ColorAction(self)
self.colorAction.colorSelected.connect(self.handleColorSelected)
self.addAction(self.colorAction)
self.addSeparator()
self.addAction('Custom Color...')
def handleColorSelected(self, color):
print(color.name())