【问题标题】:How to show selected text different from list text in QComboBox?如何在 QComboBox 中显示与列表文本不同的选定文本?
【发布时间】:2020-11-29 02:23:19
【问题描述】:

我有一个QComboBox 和一个弹出列表(QAbstractItemView),显示不同的项目(QStandardItems)。现在,我希望列表中的项目显示与选中项目不同的文本。

背景:

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名称,说“标题 2”。

我认为以下问题正是我所要求的,但显然选择了一个不起作用的答案(显然甚至根据提问者的说法):Can a QComboBox display a different value than whats in it's list?

【问题讨论】:

    标签: c++ qt qcombobox


    【解决方案1】:

    解决方案

    由于QComboBox 使用列表视图来显示值,可能是“Qt'iest”达到预期效果的方式,是使用自定义委托并修改其paint 方法中的文本,使用哈希map (QHash) 获取对应的字符串。

    示例

    这是我为您准备的一个简单示例,用于演示如何实施建议的解决方案:

    Delegate.h 这就是魔法发生的地方

    #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 仅用于演示目的

    #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);
        }
    };
    

    结果

    该示例产生以下结果:

    【讨论】:

    • 注意:此时您也可以使用不同的项目角色(如在另一个问题中)并使用 QModelIndex::data 获取那些角色,而不是维持 QHash
    • @YakovGalka,是的,也可以这样实现。
    【解决方案2】:

    最简单的方法是将 ComboBox 设置为可编辑,然后当当前项目更改时,将文本更改为您想要的任何内容。示例:

    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-&gt;comboBox-&gt;setCurrentText("Green on"); 只会在选中项目时更改文本,当您重新打开组合框时,文本将恢复为原始文本。这有点类似于我的回答here

    另一种方法是继承QComboBox 类,然后重新实现mousePressEvent 以在鼠标按下时更改模型,并在释放后将其切换回来。由于我自己没有尝试过,所以这可能会更难解决,甚至可能无法正常工作

    【讨论】:

    • 在这种情况下允许编辑组合框的文本没有多大意义,因为所有条目都应该事先知道。
    • 没错。并使其可编辑,您还允许用户在其中输入文本。正如已经提到的,这没有多大意义。特别是对于 UX。
    • 好吧,老实说,您的解决方案是我尝试过的第一件事,因此我相信它更直观。但是,它有问题,我认为应该指出这一点。你知道的,以备将来参考。除此之外,我认为这两种方法都是实现同一目标的不同方式。
    • 是的,但我的解决方案更像是一种蛮力方式,哈哈
    • :) 如果 QComboBox 提供开箱即用的功能,那么这些都是必要的。但我想,在这种情况下,现场直播太容易了。 :)
    猜你喜欢
    • 1970-01-01
    • 2016-02-02
    • 1970-01-01
    • 2018-01-06
    • 1970-01-01
    • 1970-01-01
    • 2020-02-06
    • 1970-01-01
    • 2016-05-30
    相关资源
    最近更新 更多