Название: Драг Отправлено: Igors от Ноябрь 09, 2018, 14:12 Добрый день
Юзер выделяет мышью пр-к в окне (QRect). Это действие реализовано "модально" (ну почти, псевдокод) Код И этот код повторяется десятки раз (если не сотни), и пишется еще и еще. Вот какой ф-ционал обычно реализован - ну естественно надо вернуть результат QRect (если драг не состоялся, то пустой) - почти всегда надо рисовать пр-к драга (образец - QRubberBand) - почти всегда есть еще пр-к "ограничитель" (выделение возможно только внутри него) - часто (по меньшей мере в половине случаев) есть autoScroll, т.е. если мыша оказалась за пределами "ограничителя" - область просмотра скроллится по вертикали/горизонтали Есть ли смысл это обобщить? Если да, то как Вы видите общие классы? Спасибо Название: Re: Драг Отправлено: Igors от Ноябрь 12, 2018, 09:26 И молчок :) Ну хорошо хоть нет вопросов типа "а для чего нужно выделять мышью ?". Ладно, попробуем с чего-то начать. Простецкий вариант: да написать просто ф-цию (утилиту) - и все дела. Напр
Код Очень неплохо, ф-ция сама разберется с мышью и с отрисовкой пр-ка (это верхнее "overlay" окно). Кстати в старом ОС подобная ф-ция была. Можно еще добавить параметров, напр "минимальный" пр-к и.т.п. - но это не принципиально. Чего не хватает? Вот autoScroll'а никакого нет, добрая половина случаев не покрывается. Ну понятно как/что скроллить - ф-ция знать не должна. Опять пойдем по пути наименьшего сопротивления: добавим аргумент QWidget/QObject и пусть ф-ция пуляет в него сигналами. Что Вы об этом думаете? Название: Re: Драг Отправлено: Racheengel от Ноябрь 14, 2018, 16:16 Ну я бы сделал классик-контроллер драга с соответствующими полями и функционалом.
И пусть он сигналы и "пуляет", что то типа emit dragRectChanged(QRectF newRect); Название: Re: Драг Отправлено: Igors от Ноябрь 14, 2018, 17:08 Ну я бы сделал классик-контроллер драга с соответствующими полями и функционалом. Впервые слышу о классик-контроллере, просветите. Ну и вообще развейте мысль, а то так.. намек.И пусть он сигналы и "пуляет", что то типа emit dragRectChanged(QRectF newRect); Да, и это Вы к молодняка переняли моду подавать структуры по значению? :) Название: Re: Драг Отправлено: Авварон от Ноябрь 14, 2018, 18:06 Да, и это Вы к молодняка переняли моду подавать структуры по значению? :) Ну это зависит от того, что передавать. Qrect пожалуй не стоит, а вот QPoint или там QStringView - пожалуйста Название: Re: Драг Отправлено: Racheengel от Ноябрь 14, 2018, 20:25 Ну я бы сделал классик-контроллер драга с соответствующими полями и функционалом. Впервые слышу о классик-контроллере, просветите. Ну и вообще развейте мысль, а то так.. намек.И пусть он сигналы и "пуляет", что то типа emit dragRectChanged(QRectF newRect); Да, и это Вы к молодняка переняли моду подавать структуры по значению? :) Насчет параметра - это ж как бы "сигнал", а там только сигнатура важна. Тем более при асинхронном обмене лучше все таки по значению.. но не суть. Насчет контроллера - я имел в виду, сделать отдельный класс, что то типа CRectDragController, который собственно должен обрабатывать мышиные события и отправлять в мир сигнал "рект поменялся, товарищи!" Ну наверное и рект этот самый отрисовывать, если в этом задача. как то так... Название: Re: Драг Отправлено: Igors от Ноябрь 15, 2018, 05:35 Насчет контроллера - я имел в виду, сделать отдельный класс, что то типа CRectDragController, который собственно должен обрабатывать мышиные события и отправлять в мир сигнал "рект поменялся, товарищи!" Ну наверное и рект этот самый отрисовывать, если в этом задача. Так собсно это уже и реализовано в приведенном выше псевдокоде. MouseDown крутит вторичный цикл (processEvents) блокируя клаву и возвращает true если мышь двинулась или false если кнопка мыши отпущена. Простой драг выглядит таккак то так... Код Ну ладно, втулим сюда сигнал "рект поменялся". Что получатель будет с ним делать? Организовывать autoScroll ему все равно придется с нуля - брать текущую позицию мыша, смотреть оказалась ли она за пределами области прокрутки (и насколько), заводить (или глушить) таймер и.т.п. Уникален только сам скролл (когда пришло событие таймера), а остальной ф-ционал явно общий - куда его поселить? Еще такой момент. Вот напр переставляются строки в дереве. Здесь "выделения" как такового нет, и логика навороченная, как-то тулить ее каллбэком в класс-контроллер мне не хочется. А вот песня с autoScroll та же самая. Надо как-то сделать чтобы "добро не пропадало" Название: Re: Драг Отправлено: Racheengel от Ноябрь 15, 2018, 11:34 Пусть базовый класс контроллера тогда и реализует обработку мыши и автоскролл вьюпорта.
А уже наследники его могли бы переопределить метод (вместо сигнала) типа virtual void OnDragRegionChanged(const QRect& newRect) и иметь в нем специфичную логику, как, например, выделение в дереве. Название: Re: Драг Отправлено: Igors от Ноябрь 15, 2018, 13:43 Пусть базовый класс контроллера тогда и реализует обработку мыши и автоскролл вьюпорта. А как он его реализует? В результате скролла должна измениться стартовая точка драга (startPt) - сместиться в противоположную сторону(ы) на число "проскролленных пыкселей" - а откуда это смещение взять? Причем скролл произойдет по таймеру, MouseDown на него не среагирует.А уже наследники его могли бы переопределить метод (вместо сигнала) типа Ну для выделения в дереве QRect не годится - интересует подрезанная (клипом) текущая точка мыша (куда вставлям). Ну и организация классов неудобна. Хотелось бы сделать этот драг просто методом конкретного окна, там объявить на стеке контроллер чтобы делал черновую работу. А тут - наследоваться от контроллера, перекрывать виртуал, а из него опять лезть к методам окна. Корявоvirtual void OnDragRegionChanged(const QRect& newRect) и иметь в нем специфичную логику, как, например, выделение в дереве. Название: Re: Драг Отправлено: Racheengel от Декабрь 15, 2018, 02:53 1. ну тут просто смотрим, за какую из границ порта вылезли мышом, и по таймеру скролим в обратном направлении на фиксированное кол.во пикселей.
2. тут не понял, что значит контроллер на стеке.? Название: Re: Драг Отправлено: Igors от Декабрь 15, 2018, 18:57 2. тут не понял, что значит контроллер на стеке.? За истекший месяц успел не только сделать, но и основательно забыть :) Что помню: нужно сделать класс гибким, в простом случае он делает все автоматомКод Возвращает выделенный rect. В более сложном случае берем драг на себя, а контроллер используем для аутоскролла Код Метод CDragControl::Update( QPoint & pt ) разберется с текущей позицией мыша, загонит ее в пр-к ограничитель и отскроллит если надо. Ну конечно "ретроспективно" (есть такое вумное словечко) это кажется совсем простым :) 1. ну тут просто смотрим, за какую из границ порта вылезли мышом, и по таймеру скролим в обратном направлении на фиксированное кол.во пикселей. А откуда возьмете "кол-во пикселей"? Как минимум нужен скроллбар (а его часто и нет, скролл = пробел + драг) + шаг скролла (напр может скроллиться по айтемам). Собсно я тоже ничего не придумал и решил не связываться ни с какими обобщениями. Для каждого конкретного окна пишу ф-циюКод Где dx/dy - насколько мышь вылез за пределы. В ф-ции выходит до 20 строк. Ну и наследуюсь от СDragControl. Мда, что-то не густо с "логикой гуя", не густо.. |