Evgenii Legotckoi
Evgenii Legotckoi3 мая 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 хостинг.

Вам это нравится? Поделитесь в социальных сетях!

Q
  • 24 декабря 2017 г. 18:16
  1. void Widget::hideRow()
  2. {
  3. qobject_cast<QListView *>(comboBox->view())->setRowHidden(lineEdit->text().toInt(), true);
  4. }
ВА
  • 7 августа 2018 г. 10:02

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

Evgenii Legotckoi
  • 8 августа 2018 г. 3:49

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

Комментарии

Только авторизованные пользователи могут публиковать комментарии.
Пожалуйста, авторизуйтесь или зарегистрируйтесь
1
  • 12333
  • 18 июля 2024 г. 2:34

Qt - Тест 001. Сигналы и слоты

  • Результат:63баллов,
  • Очки рейтинга-1
1
  • 12333
  • 18 июля 2024 г. 2:25

C++ - Тест 005. Структуры и Классы

  • Результат:50баллов,
  • Очки рейтинга-4
AM

C++ - Тест 005. Структуры и Классы

  • Результат:33баллов,
  • Очки рейтинга-10
Последние комментарии
d
dblas55 июля 2024 г. 8:02
QML - Урок 016. База данных SQLite и работа с ней в QML Qt Здравствуйте, возникает такая проблема (я новичок): ApplicationWindow неизвестный элемент. (М300) для TextField и Button аналогично. Могу предположить, что из-за более новой верси…
k
kmssr8 февраля 2024 г. 15:43
Qt Linux - Урок 001. Автозапуск Qt приложения под Linux как сделать автозапуск для флэтпака, который не даёт создавать файлы в ~/.config - вот это вопрос ))
АК
Анатолий Кононенко4 февраля 2024 г. 22:50
Qt WinAPI - Урок 007. Работаем с ICMP Ping в Qt Без строки #include <QRegularExpressionValidator> в заголовочном файле не работает валидатор.
EVA
EVA25 декабря 2023 г. 7:30
Boost - статическая линковка в CMake проекте под Windows Ошибка LNK1104 часто возникает, когда компоновщик не может найти или открыть файл библиотеки. В вашем случае, это файл libboost_locale-vc142-mt-gd-x64-1_74.lib из библиотеки Boost для C+…
J
JonnyJo25 декабря 2023 г. 5:38
Boost - статическая линковка в CMake проекте под Windows Сделал всё по-как у вас, но выдаёт ошибку [build] LINK : fatal error LNK1104: не удается открыть файл "libboost_locale-vc142-mt-gd-x64-1_74.lib" Хоть убей, не могу понять в чём дел…
Сейчас обсуждают на форуме
F
Fynjy22 июля 2024 г. 1:15
при создании qml проекта Kits есть но недоступны для выбора Поставил Qt Creator 11.0.2. Qt 6.4.3 При создании проекта Qml не могу выбрать Kits, они все недоступны, хотя настроены и при создании обычного Qt Widget приложения их можно выбрать. В чем может …
BlinCT
BlinCT24 июня 2024 г. 22:00
Нарисовать кривую в qml Всем привет. Имеется Лист листов с тосками, точки получаны интерполяцией Лагранжа. Вопрос, как этими точками нарисовать кривую? ChartView отпадает сразу, в qt6.7 появился новый элемент…
Evgenii Legotckoi
Evgenii Legotckoi24 июня 2024 г. 12:11
добавить qlineseries в функции Я тут. Работы оень много. Отправил его в бан.
BlinCT
BlinCT5 мая 2024 г. 2:46
Написать свой GraphsView Всем привет. В Qt есть давольно старый обьект дял работы с графиками ChartsView и есть в 6.7 новый но очень сырой и со слабым функционалом GraphsView. По этой причине я хочу написать х…
Evgenii Legotckoi
Evgenii Legotckoi2 мая 2024 г. 11:07
Мобильное приложение на C++Qt и бэкенд к нему на Django Rest Framework Добрый день. По моему мнению - да, но то, что будет касаться вызовов к функционалу Андроида, может создать огромные трудности.

Следите за нами в социальных сетях