【问题标题】:How to connect two QComboBox so that the second shows only certain items?如何连接两个 QComboBox 以使第二个仅显示某些项目?
【发布时间】:2023-03-23 16:50:01
【问题描述】:

我有两个 QComboBox 可以相互连接。

特别是,如果在第一个 QComboBox 中进行缩放,我希望在第二个 QComboBox 中也不会显示,反之亦然..

这是我的代码:

auto lingua_originaleT = new QComboBox();
lingua_originaleT->addItems({"Italiano", "Inglese", "Francese", "Spagnolo", "Portoghese", "Tedesco", "Cinese"});
auto lingua_targetT = new QComboBox();
lingua_targetT->addItems({"Italiano", "Inglese", "Francese", "Spagnolo", "Portoghese", "Tedesco", "Cinese"});

结果应该是这样的:

同样的语言也不应该出现在第二个下拉菜单中

【问题讨论】:

    标签: c++ qt connect signals-slots qcombobox


    【解决方案1】:

    一种可能的解决方案是使用 QSortFilterProxyModel 进行过滤:

    #include <QApplication>
    #include <QComboBox>
    #include <QHBoxLayout>
    #include <QSortFilterProxyModel>
    #include <QStandardItemModel>
    #include <QWidget>
    
    class FilterProxyModel: public QSortFilterProxyModel{
    public:
        using QSortFilterProxyModel::QSortFilterProxyModel;
    protected:
        bool filterAcceptsRow(int source_row, const QModelIndex &source_parent) const{
            if(filterRegExp().isEmpty())
                return true;
            return !QSortFilterProxyModel::filterAcceptsRow(source_row, source_parent);
        }
    };
    
    int main(int argc, char *argv[])
    {
        QApplication a(argc, argv);
        QWidget widget;
        widget.resize(640, 480);
        widget.show();
    
        QStandardItemModel *model = new QStandardItemModel(&widget);
        const QStringList values{"Italiano", "Inglese", "Francese", "Spagnolo", "Portoghese", "Tedesco", "Cinese"};
        for(const QString & value: values){
            model->appendRow(new QStandardItem(value));
        }
        QComboBox *lingua_originaleT = new QComboBox;
        FilterProxyModel *proxy_originalT = new FilterProxyModel(&widget);
        proxy_originalT->setSourceModel(model);
        lingua_originaleT->setModel(proxy_originalT);
    
        QComboBox *lingua_targetT = new QComboBox;
        FilterProxyModel *proxy_targetT = new FilterProxyModel(&widget);
        proxy_targetT->setSourceModel(model);
        lingua_targetT->setModel(proxy_targetT);
    
        QHBoxLayout *lay = new QHBoxLayout(&widget);
        lay->addWidget(lingua_originaleT);
        lay->addWidget(lingua_targetT);
    
        QObject::connect(lingua_originaleT, &QComboBox::currentTextChanged, proxy_targetT, &FilterProxyModel::setFilterFixedString);
        QObject::connect(lingua_targetT, &QComboBox::currentTextChanged, proxy_originalT, &FilterProxyModel::setFilterFixedString);
    
        lingua_originaleT->setCurrentIndex(0);
        lingua_targetT->setCurrentIndex(1);
    
        return a.exec();
    }
    

    【讨论】:

    • 这也很优雅:) 如果他们共享相同的模式,它不会过滤掉并删除两个框上的条目吗?
    • @Gretaas 请查看tour
    【解决方案2】:

    在内部,QCombobox 使用 QStandardItemModel - 除非您使用 setModel() 提供自定义模型。

    这意味着您可以执行以下操作:

    // Just some setup
    auto combo = new QComboBox(this);
    combo->addItems({ "Item0", "Item1", "Item2" });
    
    // Here is the interesting bit
    auto model = qobject_cast<QStandardItemModel*>(combo->model());
    auto item  = model->item(0); // <-- index in the combobox
    item->setEnabled(false); // <-- You can't select it anymore
    
    if(combo->currentIndex() == 0) // Choose another one if it's already selected
        combo->setCurrentIndex(1);
    
    // From now, Item 0 will be visible in the dropdown but not selectable by the user.
    

    我让你找到一种方法让 2 个框相互禁用其他项目(重要的是,如果选择更改,则启用它们一次)。这是一个监听每个盒子的索引变化信号并相应地更新另一个模型的问题。

    【讨论】:

    • 您的解决方案只是使其无法选择,因为该项目已禁用,但它仍然可见,这不是 OP 想要的:相同的语言不应出现在第二个下拉菜单中好
    • 这是真的。尽管从用户体验的角度来看,将两个具有相同形状、相同大小、相同项目的相同项目关联起来更容易。该项目不在此处意味着它不能作为目标语言使用。被禁用的项目意味着它可用,但由于先前的原始语言选择而无效。但是,是的,您可以争辩说我没有回答这个问题。
    【解决方案3】:

    我解决了,解决方案完美! 我是这样做的:

    lingua_originaleT = new QComboBox();
    lingua_targetT = new QComboBox();
    
        QStringList traduzioneLangList = {"Italiano", "Inglese", "Francese", "Spagnolo", "Portoghese", "Tedesco", "Cinese"};
        lingua_originaleT->clear();
        lingua_originaleT->addItems(traduzioneLangList);
        lingua_originaleT->setCurrentIndex(-1);
        lingua_targetT->clear();
        lingua_targetT->addItems(traduzioneLangList);
        lingua_targetT->setCurrentIndex(-1);
    
        connect(lingua_originaleT, &QComboBox::currentTextChanged, lingua_targetT, [=](const QString &selection) {
            auto tarLangList = traduzioneLangList;
            lingua_targetT->blockSignals(true);
            tarLangList.removeOne(selection);
            lingua_targetT->clear();
            lingua_targetT->addItems(traduzioneLangList);
            lingua_targetT->blockSignals(false);
        });
        connect(lingua_targetT, &QComboBox::currentTextChanged, lingua_originaleT, [=](const QString &selection) {
            auto tarLangList = traduzioneLangList;
            lingua_originaleT->blockSignals(true);
            tarLangList.removeOne(selection);
            lingua_originaleT->clear();
            lingua_originaleT->addItems(traduzioneLangList);
            lingua_originaleT->blockSignals(false);
        });
        lingua_originaleT->setCurrentIndex(0);
    

    非常感谢 reddit 上的@lifof!

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2014-04-27
      • 1970-01-01
      • 2018-09-06
      • 1970-01-01
      • 2013-01-15
      • 2022-06-22
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多