Russian Qt Forum
Январь 24, 2017, 22:18 *
Добро пожаловать, Гость. Пожалуйста, войдите или зарегистрируйтесь.
Вам не пришло письмо с кодом активации?

Войти
 
  Начало   Форум  WIKI (Вики)FAQ Помощь Поиск Войти Регистрация  

Страниц: [1]   Вниз
  Печать  
Автор Тема: (РЕШЕНО) Долбаный QSlider...  (Прочитано 422 раз)
Гурман
Житель матрицы
******
Offline Offline

Сообщений: 1221

Qt 2.2, 3.3, 4.5, 4,7, 4.8, 5.3, 5.6


Просмотр профиля
« : Декабрь 27, 2016, 23:32 »

Сделал плагин для дизайнера на основе QSlider чтобы можно было задавать изображения ручки и прорези. Слайдер пока только горизонтальный - вертикальный потом доделать несложно. Требуется, чтобы при изменении высоты слайдера пропорционально изменялся размер ручки. А при изменении ширины изменялась только ширина прорези. Поэтому использование таблицы стилей не подходит - с ним невозможно в дизайнере менять размеры ручки. Перегрузил paintEvent(), всё почти заработало сразу. Но проблема - прорезь рисуется на всю ширину виджета, а центр ручки бегает между левым и правым краями прорези. Соответственно, в крайних положениях половина ручки обрезается. И долбаюсь уже второй день, пытаюсь выяснить, как сделать, чтобы ширина прорези была меньше ширины виджета, и центр ручки перемещался только между краями прорези. Требуемую прорезь получил, но при этом выяснил, что все положения ручки родительский класс вычисляет не по ширине прорези, а по ширине виджета. То есть, даже если прорезь меньше виджета, то ручка всё равно бегает между крайними границами виджета и обрезается на краях. Что только не пробовал, ни в какую.

Но ведь должно же как-то правильно работать! Беру оригинальный QSlider - у него всё в порядке. Ничего не обрезается, ручка двигается между краями прорези, которая меньше виджета... Обеспокоенный Полез исходники QSlider ковырять - там чёрт ногу сломит. Вижу, где двигается слайдер, где мышиное событие обрабатывается. Но никак не могу найти - где вычисляются "точки останова", их положение в виджете. Ограничитель при перемещении ручки - это значение, а не координаты. То есть, упирается влево он при достижении заданного минимального значения. Но как попадает на свою крайнюю левую позицию? Где она задана? Причём по коду перемещения слайдера вообще не видно, как ручка "тормозит" на промежуточных позициях. Перемещение ручки вообще "плавное"! И этого же не видно в коде отрисовки ручки, там только рисование.

Кто-нибудь расковыривал исходники слайдера? Если не получится сделать, придётся реализовать на таблице стилей, а это ГОРАЗДО хуже, так как размеры ручки нельзя будет менять в дизайнере.
« Последнее редактирование: Декабрь 28, 2016, 19:18 от Гурман » Записан

2^7-1 == 127, задумайтесь...
Igors
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 9395


Просмотр профиля
« Ответ #1 : Декабрь 28, 2016, 06:04 »

Делал свой стиль, вполне реально, ничего страшного. Для слайдера отделался своим subControlRect и drawComplexControl. Это намного дешевле чем разбираться в обильных подробностях styleHint и.т.п
Записан
Гурман
Житель матрицы
******
Offline Offline

Сообщений: 1221

Qt 2.2, 3.3, 4.5, 4,7, 4.8, 5.3, 5.6


Просмотр профиля
« Ответ #2 : Декабрь 28, 2016, 11:02 »

Делал свой стиль
Это в моём случае лишнее. Мне надо только для QSlider картинки в дизайнере указывать. Ну ещё для кнопки и дайала, но там уже всё сделано как следовало, без стилей.

Нашёл наконец-то, где вычисляется позиция ручки, в моём случае это в QCommonStyle::subControlRect(). Там прямая зависимость от ширины слайдера, а не от ширины прорези. ИМХО - это баг. Но по-прежнему не понятно, как получается правильный "фирменный" слайдер, так как его позиция тоже в QCommonStyle::subControlRect() вычисляется.
« Последнее редактирование: Декабрь 28, 2016, 11:28 от Гурман » Записан

2^7-1 == 127, задумайтесь...
Гурман
Житель матрицы
******
Offline Offline

Сообщений: 1221

Qt 2.2, 3.3, 4.5, 4,7, 4.8, 5.3, 5.6


Просмотр профиля
« Ответ #3 : Декабрь 28, 2016, 19:17 »

ВСЁ! Победил... без создания собственного стиля, нафик он не нужен. Разобрался по исходникам, что управление перемещением производится в style()->subControlRect() виджета, и это вызывается прямо из paintEvent(). При этом туда надо передавать  

Код:
   QStyleOptionSlider o;
    initStyleOption(&o);

который принимает параметры текущего виджета. Если у него перед вызовом style()->subControlRect() изменить прямоугольник с помощью

Код:
   o.rect.setWidth( o.rect.width() - knobwidth );
    o.rect.moveLeft( knobwidth/2 );

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

Единственное, что удручает - это то, что в угоду разным стилям subControlRect() по разному вычисляет координаты и размеры в разных ОС. В результате выглядит это всё совсем не одинаково в Kubuntu, Android и Windows. Как надо получилось сначала только в Android. Можно было бы и свой стиль соорудить, но гораздо проще было послать нафик все эти извраты и ещё раз перед рисованием самому всё пересчитать.
« Последнее редактирование: Декабрь 28, 2016, 19:39 от Гурман » Записан

2^7-1 == 127, задумайтесь...
Страниц: [1]   Вверх
  Печать  
 
Перейти в:  

Страница сгенерирована за 0.046 секунд. Запросов: 22.