Reputation: 3691
I have a QComboBox
with a popup list (a QAbstractItemView
) showing different items (QStandardItem
s). Now, I want the item in the list to show a different text than if the item is selected.
Background:
I am creating a word-processor like style chooser where one can choose, say, "1.1 Heading 2" from the list, indicating the numbering and the style name, but when an item is chosen the combobox should only show the style name, say "Heading 2".
I thought the following question was exactly about what I was asking for but apparently an answer was chosen that does not work (apparently even according to the person asking the question): Can a QComboBox display a different value than whats in it's list?
Upvotes: 2
Views: 1367
Reputation: 8399
Since QComboBox
uses a list view to display the values, probably the "Qt'iest" way to achieve the desired effect, is to use a custom delegate and modify the text within its paint
method, using a hash map (QHash
) to get the corresponding string.
Here is a simple example I have prepared for you to demonstrate how the proposed solution could be implemented:
Delegate.h this is where the magic is happening
#include <QStyledItemDelegate>
#include <QApplication>
class Delegate : public QStyledItemDelegate
{
Q_OBJECT
public:
explicit Delegate(QObject *parent = nullptr) :
QStyledItemDelegate(parent) {}
void setHash(const QHash<int, QString> &hash) {
m_hash = hash;
}
void paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const override {
if (!index.isValid())
return;
QStyleOptionViewItem opt = option;
initStyleOption(&opt, index);
opt.text = m_hash.value(index.row());
QApplication::style()->drawControl(QStyle::CE_ItemViewItem, &opt, painter);
}
private:
QHash<int, QString> m_hash;
};
MainWindow.h only for demo purposes
#include <QWidget>
#include <QBoxLayout>
#include <QComboBox>
#include <QStandardItemModel>
#include "Delegate.h"
class MainWindow : public QWidget
{
Q_OBJECT
public:
MainWindow(QWidget *parent = nullptr)
: QWidget(parent)
{
auto *l = new QVBoxLayout(this);
auto *cmbBox = new QComboBox(this);
auto *model = new QStandardItemModel(this);
auto *delegate = new Delegate(this);
QHash<int, QString> hash;
for (int n = 0; n < 5; n++) {
// For demo purposes I am using "it#" and "item #"
// Feel free to set those strings to whatever you need
model->appendRow(new QStandardItem(tr("it%1").arg(QString::number(n))));
hash.insert(n, tr("item %1").arg(QString::number(n)));
}
delegate->setHash(hash);
cmbBox->setModel(model);
cmbBox->setItemDelegate(delegate);
l->addWidget(cmbBox);
resize(600, 480);
}
};
The example produces the following result:
Upvotes: 5
Reputation: 9331
The easiest way to do is to set the ComboBox as editable and then when the current item changes, you change the text to whatever you want. Example:
MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent)
, ui(new Ui::MainWindow)
{
ui->setupUi(this);
QStringList a = {"Red", "Green", "Blue"};
aModel.setStringList(a);
ui->comboBox->setModel(&aModel);
ui->comboBox->setEditable(true);
}
void MainWindow::on_comboBox_currentIndexChanged(const QString &arg1)
{
if (arg1 == "Green") {
ui->comboBox->setCurrentText("Green on");
} else if (arg1 == "Red") {
ui->comboBox->setCurrentText("Red on");
}
}
ui->comboBox->setCurrentText("Green on");
will only change the text when the item is selected, when you reopen the combobox, the text will be reverted back to original. This is somewhat similar to my answer here.
Another way to do this would be to inherit the QComboBox
class and then reimplement the mousePressEvent
to change the model whenever the mouse is pressed, and switch it back after releasing. This will probably be more difficult to get right or may not even work as I have not tried it myself
Upvotes: 2