Qt/C++ - Tutorial 077. QComboBox - ignoring hidden items in the drop-down list when scrolling

QComboBox, Qt, eventFilter

In one of the previous articles, it was shown how to hide some items in the QComboBox drop-down list so that the user could not select them. However, I did not pay attention to the fact that if the user hovers the mouse on the combo box itself and scrolls the mouse wheel, it can select this hidden menu item. Therefore, this behavior should be prohibited.

You can do this with the help of the mouse scrolling event scrolling within this combo box.

Depending on the structure of the program, you can do this in two ways:

  1. Inherit from the QComboBox class and override the method wheelEvent(QWheelEvent * event ).
  2. Inherit from the QObject class and override the method eventFilter(QObject* obj , QEvent * event )

By itself, the main code of the method will be similar in both cases, there will be different locations of this code. This will be determined by whether you need to create a QComboBox custom class or not.

With inheritance from QComboBox

When inheriting from QComboBox , we override the wheelEvent(QWheelEvent* event) method and check which of the lines are hidden. We will ignore all hidden lines at the event of the scratch and jump to the next available visible line.

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);
}

With the filter installed

If you do not want to create a custom QComboBox , but you need this functionality, then you can create a filter in that window (all widgets are inherited from QObject), where your QComboBox is installed.

To do this, we redefine the window method 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);
}

and install this filter on the target QComboBox

Widget::Widget(QWidget *parent) :
    QWidget(parent),
    ui(new Ui::Widget)
{
    ui->setupUi(this);
    ui->comboBox->installEventFilter(this); // Установим фильтр
}
We recommend hosting TIMEWEB
We recommend hosting TIMEWEB
Stable hosting, on which the social network EVILEG is located. For projects on Django we recommend VDS hosting.
Support the author Donate
P
  • #
  • March 19, 2020, 4:32 a.m.
  • (edited)

Здравствуйте, у меня есть вопрос по комбобоксу. Примеры из интернета со стилями не дают того, что нужно.

есть комбобокс. рядом кнопка по нажатии которой текущему элементу комбобокса устанавливается некий цвет.

QComboBox * cb
QColor color = QColorDialog::getColor( );
cb->setItemData( cb->currentIndex(), QBrush( color ), Qt::BackgroundRole );

например второму элементу такой цвет

но при наведении мыши цвет перекрывается цыетом селектора. даже если ему затать прозразный цвет.

как можно решить это?

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

P
  • #
  • March 21, 2020, 4:48 p.m.
  • (edited)

вобщем решил проблему. может пригодится кому
без наследования, переопределений , делегатов и т.д ))
не знаю насколько правильно, но всё работает.
весь фокус - несколько строк кода.
можно задать любой цвет которым будет выделяться элемент при наведении.
если цвет брать из самого элемента на котором курсор, то получется , что выделение "как бы прозрачное"
только рамочка видна.

подключение к сигналу взял из примера в документации.
как соорудить стиль из цвета - наткнулся на просторах инета.

connect(comboBox, QOverload<int>::of(&QComboBox::highlighted), [=](int index)
    {
        QColor color = ... // задаем нужный цвет. или берем цвет из элемента по индексу index
        QString style = "QComboBox QAbstractItemView { selection-background-color: rgb(%1, %2, %3); }" ;
        style =  style.arg(color.red( )).arg(color.green( )).arg(color.blue( ) );
        comboBox->setStyleSheet(style);
    });

Comments

Only authorized users can post comments.
Please, Log in or Sign up
Donate

Hello, Dear Users of EVILEG!!!

If the site helped you, then support the development of the site financially, please.

You can do it by following ways:

Thank you, Evgenii Legotckoi

DK
April 1, 2020, 8:03 a.m.
Dmitry Kozhinov

C++ - Test 001. The first program and data types

  • Result:40points,
  • Rating points-8
A
March 30, 2020, 12:47 p.m.
Anna

C++ - Test 001. The first program and data types

  • Result:60points,
  • Rating points-1
A
March 29, 2020, 12:14 p.m.
Alexanderv66

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

  • Result:71points,
  • Rating points1
Last comments
April 3, 2020, 8:06 a.m.
Konstantin Grudnitskiy

Я надеюсь вы уже разобрались в чем дело, но если вдруг нет, то проблема состоит в том, что вы пытаетесь запустить программу из интерпретатора питона. Файл main.py это уже готова…
April 3, 2020, 6:18 a.m.
Konstantin Grudnitskiy

>>> text = 'hello world'>>> ' '.join(word for word in text.split()[:-1])'hello'>>> def remove_last_word(text):... return text and ' '.join(word for word in text.s…
March 27, 2020, 2:40 p.m.
Evgenij Legotskoj

Добрый день. В конце пятой статьи скачать можете.
March 27, 2020, 2:28 p.m.
mkdir _

Здравствуйте, а можно, пожалуйста, ссылку на целые исходники, если есть?
March 27, 2020, 4:36 a.m.
Evgenij Legotskoj

Скорее всего также, как и для установки всех остальных переменых в CMake, через использование set
Now discuss on the forum
April 5, 2020, 5:09 a.m.
IscanderChe

Попробуйте CQtDeployer или windeployqt.
April 5, 2020, 2:35 a.m.
Mihailll

Так работает console.log(textEmail.text) var str = textEmail.text; var n = str.search(/^((([0-9A-Za-z]{1}[-0-9A-z\.]{1,}[0-9A-Za-z]{1})|([0-9А-Яа-я]{1}[-0-9А-я\.]{1,}[…
April 3, 2020, 12:53 p.m.
BlinCT

Само собою на компе этого незаметно.
April 3, 2020, 8:48 a.m.
Intruder

Евгений, добрый день. Спасибо!
s
April 3, 2020, 7:52 a.m.
solmik

да вроде много чего установленно, если неправильный путь указать то же самое, пробовал запустить видео через плей лист (по примерам из док)и из него назад путь взять, не получилось
EVILEG
About
Services
© EVILEG 2015-2019
Recommend hosting TIMEWEB