- 1. Что же тогда делать?
- 2. Реализация
- 1. widget.h
- 2. widget.cpp
В некоторых случаях требуется скрыть некоторые элементы из выпадающего списка QComboBox . Например, пользователю даётся возможность выбрать один из нескольких вариантов в QComboBox , но по умолчанию должен отображаться невалидный вариант, который должен отсутствовать в выпадающем списке. То есть по умолчанию выбрано что-то неправильное, что при валидации будет проверено и выдаст пользователю сообщение, что нужно выбрать один из возможных вариантов, которые доступны, тогда как неправильный вариант будет отсутствовать в списке.
При попытке найти информацию в поисковых системах по этой теме в первую очередь натыкаешься на варианты, когда пытаются использовать кастомный делегат, наследованный от QItemDelegate , или попытки играться с флагами, которые можно установить элементам в QComboBox , но оба варианты не работают.
Первый вариант с QItemDelegate не будет работать потому, что если даже сделать так, что определённый элемент не будет отрисовываться, его место нахождения тем не менее будет в списке. Просто на этом месте будет пустой прямоугольник.
Второй вариант с флагами не подходит потому, что нет такого флага, который бы заставил QComboBox скрыть определённый элемент в списке, хотя наиболее близким по значению является флаг Qt::ItemIsEnabled , но если его сбросить, то тогда текст элемента становится серым, показывая, что элемент нельзя выбрать.
Ещё можно рассмотреть вариант с моделью данных и отрисовкой элементов, но мы опять же возвращаемся к QItemDelegate , который опять же не работает.
Что же тогда делать?
Взглянем на QComboBox с другой точки зрения.
Что это такое в самом простом варианте? - Это кнопка, по клику на которую появляется выпадающий список.
Что такое выпадающий список? - Это QFrame в который помещен объект, наследованный от QAbstractItemView. А если быть точным, то QListView.
В данном случае QListView будет содержать модель данных, из которой подставляется текущий выбранный элемент в QComboBox и эта же модель данных служит для отображения списка всех элементов. А сам QListView может !ВНИМАНИЕ! скрывать строки и при этом не удалять их из модели данных!!! И в данном случае в QComboBox может отображаться в качестве текущего элемента тот элемент, который можно скрыть из выпадающего списка. WIN!!!
Реализация
Для примера реализуем следующее приложение. Есть комбобокс с пятью элементами. Есть LineEdit, в который можно написать номер элемента, который можно скрыть. И есть кнопка, по нажатию которой, мы скрываем элемент в выпадающем списке. Для проверки можно выбрать какой-нибудь элемент и скрыть именно его из списка. Тогда Вы убедитесь, что он будет отображаться на QComboBox , но в выпадающем списке он не будет виден. (Номера элементов начинаются с 0)
Приложение будет выглядеть следующим образом.
widget.h
#ifndef WIDGET_H #define WIDGET_H #include <QWidget> #include <QComboBox> #include <QPushButton> #include <QLineEdit> #include <QListView> class Widget : public QWidget { Q_OBJECT public: explicit Widget(QWidget *parent = 0); ~Widget(); private slots: void hideRow(); private: QComboBox *comboBox; QPushButton *hideButton; // кнопка по клику которой будем скрывать заданный элемент QLineEdit *lineEdit; // lineEdit, в который будем задавать элемент для скрытия QListView *listView; // указатель на список элементов }; #endif // WIDGET_H
widget.cpp
#include "widget.h" #include <QGridLayout> Widget::Widget(QWidget *parent) : QWidget(parent), comboBox(new QComboBox(this)), hideButton(new QPushButton("Hide", this)), lineEdit(new QLineEdit(this)) { QGridLayout *gridLayout = new QGridLayout(this); setLayout(gridLayout); gridLayout->addWidget(comboBox, 0, 0, 1, 2); gridLayout->addWidget(hideButton, 1, 0, 1, 1); gridLayout->addWidget(lineEdit, 1, 1, 1, 1); listView = new QListView(comboBox); comboBox->setView(listView); comboBox->addItem("0"); comboBox->addItem("1"); comboBox->addItem("2"); comboBox->addItem("3"); comboBox->addItem("4"); connect(hideButton, &QPushButton::clicked, this, &Widget::hideRow); } Widget::~Widget() { } void Widget::hideRow() { listView->setRowHidden(lineEdit->text().toInt(), true); }
А как скрыть саму запись, без удаления строки из drop-down меню?
Что простите? Откуда именно Вы собрались скрывать запись? И ищ выпадающего спика она не удаляется, а скрывается.