Евгений Легоцкой3 мая 2017 г. 12:23

Qt/C++ - Урок 064. Как скрыть элементы из выпадающего списка QComboBox

В некоторых случаях требуется скрыть некоторые элементы из выпадающего списка 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);
}

Архив с проектом

Рекомендуем хостинг TIMEWEB
Рекомендуем хостинг TIMEWEB
Стабильный хостинг, на котором располагается социальная сеть EVILEG. Для проектов на Django рекомендуем VDS хостинг.
Поддержать автора Donate
Q
  • #
  • 24 декабря 2017 г. 18:16
  1. void Widget::hideRow()
  2. {
  3. qobject_cast<QListView *>(comboBox->view())->setRowHidden(lineEdit->text().toInt(), true);
  4. }
ВА

А как скрыть саму запись, без удаления строки из drop-down меню?

Что простите? Откуда именно Вы собрались скрывать запись? И ищ выпадающего спика она не удаляется, а скрывается.

Комментарии

Только авторизованные пользователи могут публиковать комментарии.
Пожалуйста, авторизуйтесь или зарегистрируйтесь
Timeweb

Позвольте мне порекомендовать вам отличный хостинг, на котором расположен EVILEG.

В течение многих лет Timeweb доказывает свою стабильность.

Для проектов на Django рекомендую VDS хостинг

Посмотреть Хостинг
VD

C++ - Тест 001. Первая программа и типы данных

  • Результат:73баллов,
  • Очки рейтинга1
Ds

C++ - Тест 003. Условия и циклы

  • Результат:64баллов,
  • Очки рейтинга-1
o

C++ - Тест 001. Первая программа и типы данных

  • Результат:86баллов,
  • Очки рейтинга6
Последние комментарии
s

Django - Урок 023. Like Dislike система с помощью GenericForeignKey

все, я со всем разобрался!) Извините!)
s

Django - Урок 023. Like Dislike система с помощью GenericForeignKey

Доброго времени суток!) Я случайно набрел на вашу статью, и она помогла мне решить некоторые мои трудности, я прошел за вами по шагам, в попытках адаптировать это под себя, и возник вопрос. У ва…
R

Qt/C++ - Урок 026. Применение CallBack функции

Спасибо огромное!

Qt/C++ - Урок 026. Применение CallBack функции

Если не объявлять статической, то не соберётся. Не получится сделать привязку метода. Дело в том, что в процессе компиляции производится сборка с указанием конкретных участков кода в данном…
  • Anton
  • 4 августа 2020 г. 2:25

Django - Урок 039. Добавление личных сообщений и чатов на сайте - Часть 2 (Счётчик диалогов и чатов с непрочитанными сообщениями)

Может быть посоветуете как добавить необязательное поле + прокинуть его во вьюху что бы можно было отправлять небольшие документы.?
Сейчас обсуждают на форуме
s

Ключевое слово class

Если закоментить include , то ошибка будет такая : C2027(использование неопределённого типа "Autorization"). Если убрать ключевое слово class , то ошибки будет 3 : Ошибка C2143 син…

Как в Android открыть свернутое приложение?

Может быть поможет это

Динамическое изменение цветовой схемы material

как по мне, темы типа material хороши если вас полностью устраивает их стил, если пишете кастомный дизайн то имеет смысл отказаться

QT QGraphics преобразование координат

Добрый день. Да, можно перевести в координаты экрана. Используйте метод mapToGlobal() . В Qt документации на класс приводятся методы, которые внедрены в конкретном классе. В нач…
М

QML связь с моделью в C++

Спасибо.
О нас
Услуги
© EVILEG 2015-2020
Рекомендует хостинг TIMEWEB