Название: Рисование карандаша, прерывистые линии Отправлено: ecspertiza от Ноябрь 20, 2012, 18:43 Нужно в программе, дать пользователю возможность рисовать "карандашем" ну к примеру как в pain или photoshop . На первый взгляд все выглядет просто, пользователь зажал кнопку, дергает мышкой, а мы получаем координаты и соединяем их линией. Все клево, за счет одного переодичность прихода координат, если у пользователя паркинсон, то мышь дергается очень быстро и координаты приходят реже, получаются ломанные линии. Под виндой еще куда не шло, но под маком сильно заметно. Собственно вопрос, как можно либо увеличить кол-во координат, либо как то сгладить линии. Пример того что получается в аттаче
Название: Re: Рисование карандаша, прерывистые линии Отправлено: Bepec от Ноябрь 20, 2012, 18:55 Кхм.
Проще выражаясь - линия получается ломанной вместо плавной? Или я не допонял вас. Название: Re: Рисование карандаша, прерывистые линии Отправлено: ecspertiza от Ноябрь 20, 2012, 19:31 Все верно понял. И собственно она такой получается из за того что mouseMoveEvent() достаточно редко приходит.
Название: Re: Рисование карандаша, прерывистые линии Отправлено: vregess от Ноябрь 20, 2012, 19:53 А что если использовать таймер?
Название: Re: Рисование карандаша, прерывистые линии Отправлено: ecspertiza от Ноябрь 20, 2012, 19:55 Не думал об этом, но на первый взгляд кажется костылем :) хотя по идее должно сработать, может есть еще какие то варианты ?
Название: Re: Рисование карандаша, прерывистые линии Отправлено: Bepec от Ноябрь 20, 2012, 20:06 Я согласен с ck.
Таймер, QCursor::pos() и количество точек у тебя вырастет в разы. Причём, насколько я пробовал, это совсем не грузит систему и программу :) Название: Re: Рисование карандаша, прерывистые линии Отправлено: ecspertiza от Ноябрь 20, 2012, 20:10 Я за ооп беспокоюсь ))) Просто в софте есть несколько инструментов и все принимают координаты именно через mouseMoveEvent наследуясь при этом от одного родителя, а если карандаш будет через таймер работать, это несколько поломает картину. Ну да ладно, оставлю таймер на крайний случай, подумаю пока как еще можно сделать. Где то слышал что можно попробовать рисовать не линию ,а кривую базье, мол это должно "сгладить углы", но пока не представляю как это можно сделать.
Название: Re: Рисование карандаша, прерывистые линии Отправлено: Igors от Ноябрь 20, 2012, 20:20 Где то слышал что можно попробовать рисовать не линию ,а кривую базье, мол это должно "сгладить углы", но пока не представляю как это можно сделать. Ну только "Безье" :) Этот вариант не равен "карандашу" (в его бытовом понимании). Хотя с др стороны - толку с того карандаша - кот наплакал. Вот был бы планшет или др устройство - тогда да, а просто с мышей доводит юзверя до нервного срыва :)Название: Re: Рисование карандаша, прерывистые линии Отправлено: V1KT0P от Ноябрь 20, 2012, 21:28 Нужно в программе, дать пользователю возможность рисовать "карандашем" ну к примеру как в pain или photoshop . На первый взгляд все выглядет просто, пользователь зажал кнопку, дергает мышкой, а мы получаем координаты и соединяем их линией. Все клево, за счет одного переодичность прихода координат, если у пользователя паркинсон, то мышь дергается очень быстро и координаты приходят реже, получаются ломанные линии. Во первых Qt возможно может пропускать часть событий мыши(именно движения). Насколько мне известно например при ресайзе формы часть событий пропускается дабы сдвиг на пиксель не преводил к ресайзу если сразу за ним последует еще несколько, а подождет немного ).Во вторых я бы делал примерно так(вроде так и сделано в нормальных редакторах): 1) Находим способ определять координаты мыши( посмотреть флаги кьюта, отдельный поток которых фиксирует координаты и т.д. ). 2) При движении эти координаты кладем в контейнер. 3) Отдельный поток достает из этого контейнера координаты и в фоне рисует. В результате если пользователь проведет красивую линию мышкой, но комп не справится то получится нормальное изображение хоть и с задержкой. Пользователей это намного больше устроит чем подвисание мыши. Название: Re: Рисование карандаша, прерывистые линии Отправлено: ecspertiza от Ноябрь 20, 2012, 22:00 а вот это интересная идея, попробую сделать.
Название: Re: Рисование карандаша, прерывистые линии Отправлено: ecspertiza от Ноябрь 21, 2012, 10:48 Сделал как советовал V1KT0P, работает хорошо, на нажатие мыши запускаю поток, который в буфер собирает точки, на отпускание завершаю поток, на движение из буфера рисую по точкам.
Название: Re: Рисование карандаша, прерывистые линии Отправлено: panAlexey от Ноябрь 21, 2012, 13:45 Сделал как советовал V1KT0P, работает хорошо, на нажатие мыши запускаю поток, который в буфер собирает точки, на отпускание завершаю поток, на движение из буфера рисую по точкам. Интересно код посмотреть.Название: Re: Рисование карандаша, прерывистые линии Отправлено: ecspertiza от Ноябрь 21, 2012, 14:17 Из проекта вырывать не охото, щас объясню как сделал если будет не понятно то накидаю пример простой
есть некий класс(буду писать примерно) описание Код: class PenGraphItem : public AbstractGraphItem реализация Код: void pCreateBufferPoint(QList<QPoint> *lstPoint, bool *stop) ну как то так Название: Re: Рисование карандаша, прерывистые линии Отправлено: Igors от Ноябрь 21, 2012, 14:50 Код: void PenGraphItem::mouseMoveEvent(QGraphicsSceneMouseEvent *event) Название: Re: Рисование карандаша, прерывистые линии Отправлено: ecspertiza от Ноябрь 21, 2012, 15:02 Да, вы правы, поправил таким образом
Код: void pCreateBufferPoint(QList<QPoint> *lstPoint, bool *stop) заодно впилил проверку на то что бы одинаковые точки в конец не добавлялись, если юзверь просто так зажал кнопку. Так вроде все кошерно. Название: Re: Рисование карандаша, прерывистые линии Отправлено: twp от Ноябрь 21, 2012, 17:49 Код: class PenGraphItem : public AbstractGraphItem Или это произошло из-за усечения настоящего кода программы? Название: Re: Рисование карандаша, прерывистые линии Отправлено: ecspertiza от Ноябрь 22, 2012, 08:53 Уберите указатели и взгляните на код :) Станет сразу ясно что значения я не получу, более того даже не смогу остановить тред :) Я думал это очивидно :)
Название: Re: Рисование карандаша, прерывистые линии Отправлено: Igors от Ноябрь 22, 2012, 09:25 Уберите указатели и взгляните на код :) Станет сразу ясно что значения я не получу, более того даже не смогу остановить тред :) Я думал это очивидно :) Мне лично не очень :) Почему значения не получить и даже не остановить ???Название: Re: Рисование карандаша, прерывистые линии Отправлено: ecspertiza от Ноябрь 22, 2012, 10:00 ок, вот допустим я передаю в ф-цию pCreateBufferPoint не указатель на список, а просто копированием, что получится ? Получится что внутри треда список то заполнится, но в ф-ции mouseMoveEvent список будет пустой, опять же из за копирования, тоже и с m_stopThreadBuff изменять смогу его сколько угодно, но на тред это никак не повлияет. Может вы хотите предложить другой вариант ? :) Я просто не совсем понимаю.
Название: Re: Рисование карандаша, прерывистые линии Отправлено: _OLEGator_ от Ноябрь 22, 2012, 10:03 Другой вариант - передача не по указателю, а по ссылке.
Название: Re: Рисование карандаша, прерывистые линии Отправлено: Igors от Ноябрь 22, 2012, 10:08 Можно по ссылке, можно и по указателю
Код Объявлять-то члены указателями необязательно, хотя это - дело вкуса Название: Re: Рисование карандаша, прерывистые линии Отправлено: ecspertiza от Ноябрь 22, 2012, 10:30 А, ну если вопрос стоял следующим образом :"Почему указатели ,а не ссылки?". То тут не скажу почему так :) Указатели первые в голову пришли.
Название: Re: Рисование карандаша, прерывистые линии Отправлено: twp от Ноябрь 22, 2012, 13:56 Уберите указатели и взгляните на код :) Станет сразу ясно что значения я не получу, более того даже не смогу остановить тред :) Я думал это очивидно :) Я понял, что для pCreateBufferPoint необходимо передавать или указатели или ссылки, но вот зачем объявлять члены класса как указатели? Тогда, по идее, в конструкторе нужно выделять память для этих переменных, а потом удалять в деструкторе (что как по мне не имеет смысла).И на счет потокобезопасности. В pCreateBufferPoint используется локальный экземпляр QMutex, что никак не защитит от возможных проблем. По идее нужно локировать один и тот же экземпляр QMutex в pCreateBufferPoint() и в mouseMoveEvent(). |