crossplatform.ru

Здравствуйте, гость ( Вход | Регистрация )

> Прокрутка в QScrollArea
Анна
  опции профиля:
сообщение 26.2.2019, 18:00
Сообщение #1


Активный участник
***

Группа: Участник
Сообщений: 276
Регистрация: 22.5.2008
Из: Зеленоград
Пользователь №: 181

Спасибо сказали: 30 раз(а)




Репутация:   4  


Суть проблемы:
Есть очень длинная форма для заполнения с QSpinBox, с QComboBox и т.п. Поскольку окно ограничено в размерах, то форма размещена на QScrollArea.
При кручении колёсика и прокрутке формы курсор мыши может оказаться на QSpinBox или QComboBox, и тогда их значения резко меняются.

Хочется, чтобы прокрутку формы можно было осуществлять только таская бегунок скроллера мышкой.
Пожалуйста, помогите реализовать. А то просто зашиваюсь по времени.
Если есть возможность "прихлопнуть" возможность изменения значений QSpinBox или QComboBox при вращении колёсика, такой вариант тоже сгодится. Может, такой вариант даже больше подойдёт.
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
4 страниц V   1 2 3 > »   
Начать новую тему
Ответов (1 - 9)
Алексей1153
  опции профиля:
сообщение 27.2.2019, 7:44
Сообщение #2


фрилансер
******

Группа: Участник
Сообщений: 2890
Регистрация: 19.6.2010
Из: Обливион
Пользователь №: 1822

Спасибо сказали: 215 раз(а)




Репутация:   34  


Анна, прочитай описание
void QWidget::wheelEvent(QWheelEvent *event)

у тебя есть несколько вариантов:

1) для виджета scrollarea->widget запретить обработчик wheelEvent (тогда прокрутка будет возможна только ползунком)

2) для всех чайлдов scrollarea->widget поставить фильтр installEventFilter, а в eventFilter запрещать выполнение прокрутки чайлдов QEvent::Wheel. Тогда останется возможность всё крутить колесом, но контролы не будут дёргаться

3) самый сложный и самый "красивый" вариант: частично как №2 , но разрешать обработку прокрутки в чайлде, если на нём стоит фокус. Если же прокрутка производится не в чайлде, то фокус с чайлда убирать на scrollarea. Тогда чайлды будут иметь свою крутилку только тогда, когда по нему щёлкнули и сразу стали крутить колесо. Когда курсов уехал по scrollarea->widget, чайлдовая крутилка отключается

Сообщение отредактировал Алексей1153 - 27.2.2019, 7:49
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
Анна
  опции профиля:
сообщение 27.2.2019, 11:16
Сообщение #3


Активный участник
***

Группа: Участник
Сообщений: 276
Регистрация: 22.5.2008
Из: Зеленоград
Пользователь №: 181

Спасибо сказали: 30 раз(а)




Репутация:   4  


Спасибо.
Совсем забыла про installEventFiltr(). Берегитесь, спинбоксы!!!

Вообще, для меня QSpinBox, с одной стороны самый необходимый класс, но самый ненавидимый: либо предоставляет слишком много возможностей там, где мне не надо, либо не позволяет самых простых вещей. Например, мне нужно вводить в диапазоне для unsigned intили long long, и всё, приплыли.
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
Алексей1153
  опции профиля:
сообщение 27.2.2019, 13:20
Сообщение #4


фрилансер
******

Группа: Участник
Сообщений: 2890
Регистрация: 19.6.2010
Из: Обливион
Пользователь №: 1822

Спасибо сказали: 215 раз(а)




Репутация:   34  


Анна, где диапазон типа unsigned int или long long, там стрелки бесполезны, используй QLineEdit (опционально - с QRegExp валидатором)

я QSpinBox вообще не помню, чтобы пользовался. Самый бесполезный контрол, наверное )
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
Анна
  опции профиля:
сообщение 27.2.2019, 15:31
Сообщение #5


Активный участник
***

Группа: Участник
Сообщений: 276
Регистрация: 22.5.2008
Из: Зеленоград
Пользователь №: 181

Спасибо сказали: 30 раз(а)




Репутация:   4  


Не скажите. Многие инженеры стрелочками спинбоксов пользуются, чтобы как на аппаратуре: сперва ввёл значение, а потом меняешь его с каким-то шагом.

Пришлось для long long написать. Это решило проблему unsigned int.
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
Анна
  опции профиля:
сообщение 28.2.2019, 12:48
Сообщение #6


Активный участник
***

Группа: Участник
Сообщений: 276
Регистрация: 22.5.2008
Из: Зеленоград
Пользователь №: 181

Спасибо сказали: 30 раз(а)




Репутация:   4  


Не скажите. Многие инженеры стрелочками спинбоксов пользуются, чтобы как на аппаратуре: сперва ввёл значение, а потом меняешь его с каким-то шагом.

Пришлось для long long написать свой спинбокс. Это решило проблему unsigned int.
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
Анна
  опции профиля:
сообщение 28.2.2019, 16:32
Сообщение #7


Активный участник
***

Группа: Участник
Сообщений: 276
Регистрация: 22.5.2008
Из: Зеленоград
Пользователь №: 181

Спасибо сказали: 30 раз(а)




Репутация:   4  


В общем, получился такой вариант:

bool MyWidget::eventFilter(QObject *target, QEvent *event)
{
    if(event->type() == QEvent::Wheel)
    {
        const char *className = target->metaObject()->className();
        if(QString(className) == QString("QComboBox"))
        {
             QCoreApplication::sendEvent(ui.scrollArea, event);
                         return true;
        }
        if(QString(className) == QString("QSpinBox") && !((QWidget*)target)->hasFocus() )
        {
            QCoreApplication::sendEvent(ui.scrollArea, event);
                        return true;
        }
    }
    return QWidget::eventFilter(target, event);
}


(Исправила немного, потому что в первом варианте фигня получилась. Так вроде бы правильно)

В конструкторе MyWidget у всех спинбоксов и комбобоксов вызываю installEventFilter(this), и устанавливаю StrongFocus.

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

Сообщение отредактировал Анна - 4.3.2019, 10:15
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
Анна
  опции профиля:
сообщение 1.3.2019, 14:43
Сообщение #8


Активный участник
***

Группа: Участник
Сообщений: 276
Регистрация: 22.5.2008
Из: Зеленоград
Пользователь №: 181

Спасибо сказали: 30 раз(а)




Репутация:   4  


Осталось только выудить спинбоксы, которые размещены на других пользовательских виджетах в этой форме.
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
Алексей1153
  опции профиля:
сообщение 1.3.2019, 20:03
Сообщение #9


фрилансер
******

Группа: Участник
Сообщений: 2890
Регистрация: 19.6.2010
Из: Обливион
Пользователь №: 1822

Спасибо сказали: 215 раз(а)




Репутация:   34  


Анна,


Раскрывающийся текст
вместо такой конструкции

const char *className = target->metaObject()->className();
if(QString(className) == QString("QComboBox"))
{
    ...
}


удобнее использовать такую
if(auto* w=dynamic_cast<QComboBox*>(target))
{
    w->...
}


накидал вот вариант обработчика. В аттаче файлы тестового диалога, создай диалог, чтобы посмотреть работу класса обработчика:

    MyWidget dlg(0);
    dlg.exec();


Прикрепленный файл  CMyScrollHandler.zip ( 2.87 килобайт ) Кол-во скачиваний: 260


Сообщение отредактировал Алексей1153 - 1.3.2019, 20:05
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
Анна
  опции профиля:
сообщение 4.3.2019, 10:57
Сообщение #10


Активный участник
***

Группа: Участник
Сообщений: 276
Регистрация: 22.5.2008
Из: Зеленоград
Пользователь №: 181

Спасибо сказали: 30 раз(а)




Репутация:   4  


Цитата(Алексей1153 @ 1.3.2019, 20:03) *
Анна, вместо такой конструкции

const char *className = target->metaObject()->className();
if(QString(className) == QString("QComboBox"))
{
    ...
}


удобнее использовать такую
if(auto* w=dynamic_cast<QComboBox*>(target))
{
    w->...
}


Действительно. Я собиралась к этому куску вернуться. Уж как-то не рационально получалось. За имена классов зацепилась, потому что недавно пришлось их в лог выводить.
Правда, обычно я использую qobject_cast, но думаю, большой разницы нет.

......

do {} while(0);

Забавная конструкция! Никогда с такой не сталкивалась, но возможность использовать break; удобна. Про использование в макросах тоже почитала.

Сообщение отредактировал Анна - 4.3.2019, 11:46
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение

4 страниц V   1 2 3 > » 
Быстрый ответОтветить в данную темуНачать новую тему
Теги
Нет тегов для показа


2 чел. читают эту тему (гостей: 2, скрытых пользователей: 0)
Пользователей: 0




RSS Текстовая версия Сейчас: 9.12.2019, 6:04