0

I would like to make a combo box that selects some contents associated with colors. I want the background of the contents to show the color. I have achieved this:

QList<QString> names;
QList<QColor> bgColors;
QList<QColor> fgColors;
QComboBox* colorComboBox = new QComboBox();
for(int i = 0; i < names.size(); ++i)
{
    colorComboBox->addItem(names.at(i), bgColors.at(i));
    const QModelIndex idx = colorComboBox->model()->index(i, 0);
    colorComboBox->model()->setData(idx, bgColors.at(i), Qt::BackgroundColorRole);
    colorComboBox->model()->setData(idx, fgColors.at(i), Qt::ForegroundRole);
}

The combo box shows the text I want, with the background color I want (not as delicate as the ColorEditorFactory example, which only shows a small rectangle next to the text, but this is how I wanted it).

What I need:

Once a row/color is selected, I would like the combo box to show the color. As is now, the combo box when closed shows the text but not the color.

enter image description here

How can I change the color of the combo box header ? (I mam calling it header but it may have a different name, not sure - the part that shows above the table used for selection and when the combo box is closed)

Edit: I tried to set a stylesheet in a slot on currentIndexChanged:

setStyleSheet("QComboBox { color: " + fgColor +
             "; background-color: " + bgColor + "; }");

Result: it changed the entire combo box in that color, forgetting the initial colors.

setStyleSheet("QComboBox:!on { color: " + fgColor +
             "; background-color: " + bgColor + "; }");

Result: it changed the color nicely when not selected - but the highlight and the header are gray and hard to read, I wish I could change it also. And when I hover, the entire combo color changes to the last one I set.

enter image description here

The answer may be in stylesheets - if I can figure out what property applies to the header.

Thalia
  • 13,637
  • 22
  • 96
  • 190

1 Answers1

1

If I understand well, you want to change the color of the QComboBox header as soon as you click on an item. I have this code which is working for me :

In the .cpp file :

myClass::init() // called in the constructor of myClass
{
    names.clear();
    names.append("One");
    names.append("Two");
    names.append("Three");

    bgColors.clear();
    bgColors.append(QColor("blue"));
    bgColors.append(QColor("red"));
    bgColors.append(QColor("green"));

    fgColors.clear();
    fgColors.append(QColor("yellow"));
    fgColors.append(QColor("magenta"));
    fgColors.append(QColor("cyan"));

    colorComboBox = new QComboBox();
    colorComboBox->setItemDelegate(new SelectionKillerDelegate);

    // don't know why but this line seems important; uncomment it,
    // and the text in the QComboBox (not the items) will be highlighted
    colorComboBox->setStyleSheet("QComboBox { border-radius: 1px; }");

    for(int i = 0; i < names.size(); ++i)
    {
        colorComboBox->addItem(names.at(i), bgColors.at(i));
        const QModelIndex idx = colorComboBox->model()->index(i, 0);
        colorComboBox->model()->setData(idx, bgColors.at(i), Qt::BackgroundColorRole);
        colorComboBox->model()->setData(idx, fgColors.at(i), Qt::ForegroundRole);
    }

    connect(colorComboBox, SIGNAL(currentIndexChanged(int)), this, SLOT(comboBoxChanged(int)));
}


void myClass::comboBoxChanged(int index)
{
    QColor forecolor = (QColor) (colorComboBox->itemData(index, Qt::ForegroundRole).value<QColor>());
    QString fgColor = forecolor.name(QColor::HexRgb);

    QColor backcolor = (QColor) (colorComboBox->itemData(index, Qt::BackgroundRole).value<QColor>());
    QString bgColor = backcolor.name(QColor::HexRgb);

    setStyleSheet("QComboBox { color: " + fgColor + "; background-color: " + bgColor + "; }");

}

In the .h file (thanks to this answer for the subclass of QItemDelegate which allows you to have items of QComboBox selected but not highlighted) :

class SelectionKillerDelegate : public QItemDelegate
{
    virtual void paint(QPainter *painter,
        const QStyleOptionViewItem &option,
        const QModelIndex &index) const override
     {
         QStyleOptionViewItem myOption = option;
         myOption.state &= (~QStyle::State_Selected);
         QItemDelegate::paint (painter, myOption, index);
     }
 };

private : 
    QComboBox* colorComboBox;
    QList<QString> names;
    QList<QColor> bgColors;
    QList<QColor> fgColors;

public slots :
    void comboBoxChanged(int);

I hope it will work for you too.

Community
  • 1
  • 1
IAmInPLS
  • 4,051
  • 4
  • 24
  • 57
  • This is awesome ! I had it working eventually with style sheets but I think this is easier. I just can't understand the `setStyleSheet("QComboBox { border-radius: 1px; }");` requirement - because it gets overwritten in the change slot anyway... – Thalia May 20 '16 at 14:25
  • Me neither , but do you notice the same thing as me? If you comment this line, you have the QComboBox text highlighted again... I have not the skills yet to understand that behavior haha – IAmInPLS May 20 '16 at 14:36
  • The text in the QComboBox ? that is still highlighted for me - now that you mentioned it, I inserted it in the slot style sheet and it removes highlighting !!! :-) Thanks again :-) – Thalia May 20 '16 at 14:41
  • This is fascinating - it seems the only thing I really needed was that border radius - the ItemDelegate subclass does only remove the highlighted state on the list view, which I may or may not want (I'll see how people like it, nice to have the option). That is surely a bug... – Thalia May 20 '16 at 14:56