Qt/C++ - Урок 077. QComboBox - игнорирование скрытых пунктов в выпадающем списке при скроллинге

QComboBox, Qt, eventFilter

В одной из предыдущих статей было показано, как скрыть некоторые пункты в выпадающем списке QComboBox , чтобы пользователь не мог их выбрать. Однако я не обратил внимание на то, что если пользователь наведёт курсор мыши на сам комбобокс и прокрутит колёсико мышки, то он сможет выбрать данный скрытый пункт меню. Следовательно такое поведение следует запретить.

Сделать это можно с помощью перехвата события прокрутки колёсика мышки в рамках данного комбобокса.

В зависимости от структуры программы можно сделать это двумя способами:

  1. Наследоваться от класса QComboBox и переопределить метод wheelEvent(QWheelEvent * event ).
  2. Наследоваться от класса QObject и переопределить метод eventFilter(QObject* obj , QEvent * event )

Сам по себе основной код метода будет аналогичен в обоих случаях, будет различно местонахождения данного кода. Это будет определяться тем, требуется ли вам создавать кастомный класс QComboBox или нет.

С наследованием от QComboBox

При наследовании от QComboBox переопределим метод wheelEvent(QWheelEvent * event ) и будем проверять, какие из строк скрытые. Все скрытые строки при событии прокрытки будем игнорировать и перескакивать на следующую доступную видимую строку.

void CustomComboBox::wheelEvent(QWheelEvent* event)
{
    int row = this->currentIndex();
    int count = this->count();
    QListView* dropdownList = static_cast<QListView*>(this->view());

    do
    {
        event->angleDelta().y() < 0 ? ++row : --row;
        if (row >= 0 && row < count && !dropdownList->isRowHidden(row))
        {
            this->setCurrentIndex(row);
            return;
        }
    }
    while (row >= 0 && row < count);
}

С установкой фильтра

Если же вы не хотите создавать кастомный QComboBox , но вам требуется данный функционал, то вы можете создать фильтр в том окне (все виджеты наследованы от QObject ), где установлен ваш QComboBox.

Для этого переопределим у окна метод eventFilter(QObject* obj , QEvent * event ).

bool Widget::eventFilter(QObject* obj, QEvent *event)
{
    if (event->type() == QEvent::Wheel)
    {
        QWheelEvent *wheelEvent = static_cast<QWheelEvent*>(event);
        QComboBox* comboBox = static_cast<QComboBox*>(obj);

        int row = comboBox->currentIndex();
        int count = comboBox->count();
        QListView* dropdownList = static_cast<QListView*>(comboBox->view());

        do
        {
            wheelEvent->angleDelta().y() < 0 ? ++row : --row;
            if (row >= 0 && row < count && !dropdownList->isRowHidden(row))
            {
                comboBox->setCurrentIndex(row);
                return true;
            }
        }
        while (row >= 0 && row < count);

        return true;
    }

    return QObject::eventFilter(obj, event);
}

и установим этот фильтр на целевой QComboBox

Widget::Widget(QWidget *parent) :
    QWidget(parent),
    ui(new Ui::Widget)
{
    ui->setupUi(this);
    ui->comboBox->installEventFilter(this); // Установим фильтр
}
Виртуальный хостинг со скидкой 10 процентов
Виртуальный хостинг со скидкой 10 процентов
EVILEG предлагает надёжный хостинг со скидкой 10% на виртуальный хостинг и 5% на VPS
Поддержать автора Donate

Комментарии

Только авторизованные пользователи могут публиковать комментарии.
Пожалуйста, авторизуйтесь или зарегистрируйтесь
25 мая 2019 г. 16:20
Андрей Янкович

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

  • Результат:93баллов,
  • Очки рейтинга8
m
19 мая 2019 г. 1:49
mahhaki

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

  • Результат:78баллов,
  • Очки рейтинга2
S
17 мая 2019 г. 13:14
SunBro

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

  • Результат:42баллов,
  • Очки рейтинга-8
Последние комментарии
21 мая 2019 г. 20:10
Дмитрий

Приветствую! Я думаю дойдёт и до этого, но пока изучать его у меня нет желания.
20 мая 2019 г. 19:20
Евгений Легоцкой

Добрый день! Вы не думали разместить репозиторий проекта на GitHub?
P.
18 мая 2019 г. 14:03
PELMYACH .

Спасибо большое! Вскоре буду разбираться!
18 мая 2019 г. 9:13
Евгений Легоцкой

Добрый день! Отнимать значение общего счётчика можно в деструкторе класса кнопки QDynamicButton::~QDynamicButton(){ ResID--;} При этом я бы ещё переустанавливал значения вс...
P.
14 мая 2019 г. 22:33
PELMYACH .

Здравствуйте!А не подскажите, как можно при удалении какой либо кнопки, у щётчика отнять значение?Дабы например четвёртой кнопке соответствовал ID 4, а не 5 скажем
Сейчас обсуждают на форуме
24 мая 2019 г. 6:48
Евгений Легоцкой

Если там будут только перечисления внутри namespace, то жа, достаточно будет заголовочного файла
24 мая 2019 г. 6:28
Андрей Янкович

работает любой http сервер, и можно использовать обсалютно любой портпример <RemoteRepositories> <Repository> <Url>http://178.124.160.6:3030/A/B&l...;
23 мая 2019 г. 14:40
Михаиллл

Попробовал сделать этот запрос по http и получил json файл. request.setUrl(QUrl("https://jsonplaceholder.typicode.com/todos/1")); Как Вы думаете, почему https не работает и как это и...
23 мая 2019 г. 10:42
Михаиллл

Спасибо, помогло.
23 мая 2019 г. 6:31
Евгений Легоцкой

Для задач и граф-то не нужен. Достаточно будет таблицы в локальной базе данных SQLite, в которой указывается задача, время и т.д. В этом разделе есть примеры по работа с базой д...

Для зарегистрированных пользователей на сайте присутствует минимальное количество рекламы

EVILEG
О нас
Услуги
Присоединяйтесь к нам
© EVILEG 2015-2019
Рекомендует хостинг TIMEWEB