Search code examples
qtqt5qcombobox

Can a QComboBox display a different value than whats in it's list?


Using Qt 5.9 on Linux, I have a QComboBox with several labels.

qc = new QComboBox;
qc->addItem(tr("Red"));
qc->addItem(tr("Green"));
qc->addItem(tr("Blue"));

Lets say a user activates the QComboBox and the 3 color labels are shown in the drop down list. The user then selects the 1st item (red).

What I want to do is have the QComboBox display a different value than what was selected. I.e., if red is selected, then a number is shown, possibly 1 for the first item (or it could be an R for Red), and if green is selected, then display 2 (or G) for the second item.

My goal in doing this is to use less display space (less wide) than is actually necessary to show the complete text of the selection because some of my item strings are quite long and a much shorter label is desired when the QComboBox is not activated in it's drop down state. Besides, the item strings are descriptive and abbreviations would work better for displaying.

Edit:
Using Marek's example, thought this might help. Here's what I have. I'm expecting if the user selects from the list, then an R, G, or a B should be displayed after.

QStandardItem *red = new QStandardItem();
red->setData(tr("Red"), Qt::DisplayRole);
red->setData("R", Qt::UserRole);

QStandardItem *green = new QStandardItem();
green->setData(tr("Green"), Qt::DisplayRole);
green->setData("G", Qt::UserRole);

QStandardItem *blue = new QStandardItem();
blue->setData(tr("Blue"), Qt::DisplayRole);
blue->setData("B", Qt::UserRole);

QStandardItemModel *rgb_model = new QStandardItemModel(this);
rgb_model->setItem(0, red);
rgb_model->setItem(1, green);
rgb_model->setItem(2, blue);

QComboBox *rgb_cb = new QComboBox();
rgb_cb->setModel(rgb_model);

I get the feeling it's because I don't quite understand how to use Qt::UserRole.


Solution

  • Yes it is possible. QComboBox uses data model to manage items. You have to provide own data model, with items with respective data values.

    QStandardItem *itme1 = new QStandardItem();
    item1->setData(tr("Red"), Qt::DisplayRole);
    item1->setData("1", Qt::UserRole); // note doesn't have to be a string.
    
    QStandardItem *itme2 = new QStandardItem();
    item2->setData(tr("Green"), Qt::DisplayRole);
    item2->setData("2", Qt::UserRole);
    
    QStandardItemModel *model = new QStandardItemModel(this);
    mode->setItem(1, item1);
    mode->setItem(2, item2);
    
    qc->setModel(model);
    

    It should work, but I didn't test it. At least this should be some clue.

    Please review QComboBox documentation, especially about roles.


    Another solution is use translations with multiple lengths. You can provide couple translation for a single string. Each translation should be graphically shorter than earlier one.

    In such situation QString contains all possibilities separated by spatial character. When such string is rendered first substring (between separators) which will fit available space will be used.

    Now I do not remember what is the separator value. I've used this very long time ago (with Qt 4.8) and now can't find reference for it.