Название: Очередность событий Отправлено: Igors от Апрель 14, 2015, 12:43 Добрый день
Есть несколько окон с OpenGL рисование которых может быть достаточно долгим. Когда юзер что-то изменил я вызываю update для всех окон нуждающихся в перерисовке, в результате получаю paintEvent. И вот когда юзер- пулеметчик выбирает слишком быстро - получается эффект засорившейся сливной трубы. Напр за секунду он успел что-то изменить 4 раза, за это время еще и первое обновление не успело. Потом рисуется второе нажатие и.т.д. А надо рисовать сразу 4-е, последнее. Как этого добиться? Спасибо Название: Re: Очередность событий Отправлено: Swa от Апрель 14, 2015, 13:07 Первое что приходит на ум - задержка. Рендер запускается через, например, 0,5 - 1 сек с последнего действия юзера.
Название: Re: Очередность событий Отправлено: Bepec от Апрель 14, 2015, 13:48 Менеджер обновления, самый простейший как и предложили обновление по таймеру. Ну или заморочиться с очередями.
Название: Re: Очередность событий Отправлено: __Heaven__ от Апрель 14, 2015, 14:05 Я бы использовал очереди и таймер
Название: Re: Очередность событий Отправлено: Igors от Апрель 14, 2015, 14:22 Не в первый раз наблюдаю этот эффект - какое-то решение предложено (причем автор даже не говорил "хорошее"), и оно тут же одобряется, без всякого осмысления :)
А если объект двигать надо, то как, рывками через пол-секунды? А если геометрии мало или карта приличная? Наверное надо "подбирать скорость", интервал (ох и долго тут один про это спрашивал, до сих пор помню "Это все ясно, но какая ..." - и так N раз :)) Мужчины, ну как-то все-таки думать надо :) Название: Re: Очередность событий Отправлено: Bepec от Апрель 14, 2015, 14:27 Если надо то двигайте. А так четко поставлена задача - проредить поток перерисовок от пользователя.
Там хоть 100 хоть 1кк событий перерисовки быть может. А время перерисовки мы не знаем и рассчитать не можем. Следовательно сделать движение объекта "плавным" мы не в силах. И вообще - мы говорим о перерисовке. Пользун что то поменял - нужно перерисовывать всё, в том числе и этот ваш движущийся объект, ибо он "старый". PS конкретизируйте тогда свои требования, у вас с этим проблема если честно. Если вам нужна плавная картинка с постоянно меняющимися параметрами и полным интерактивом, мб стоит тогда подумать о наращивании мощности железа, а не ловле блох с невнятными требованиями? Название: Re: Очередность событий Отправлено: Swa от Апрель 14, 2015, 14:28 Не в первый раз наблюдаю этот эффект - какое-то решение предложено (причем автор даже не говорил "хорошее"), и оно тут же одобряется, без всякого осмысления :) А если объект двигать надо, то как, рывками через пол-секунды? А если геометрии мало или карта приличная? Наверное надо "подбирать скорость", интервал (ох и долго тут один про это спрашивал, до сих пор помню "Это все ясно, но какая ..." - и так N раз :)) Мужчины, ну как-то все-таки думать надо :) Вы не описали подробно условия задачи, а говорите что решение вам не подходит. В первом посте было: "И вот когда юзер- пулеметчик выбирает слишком быстро" - из этого я сделал вывод, что пользователь набирает текст. Для этой ситуации, ИМХО, таймер подходит. Если у вас не только набор текста, опишите подробнее, как устроен софт и чего нужно добиться. Название: Re: Очередность событий Отправлено: Igors от Апрель 14, 2015, 14:50 Если у вас не только набор текста, опишите подробнее, как устроен софт и чего нужно добиться. Случаев много, один из них: объекты отображаются в неск окнах, есть еще окно со списком объектов. Юзер может выбирать из списка кликнув на айтем мышей, выбранный объект должен подсветиться во всех окнах - вот собственно и все.Кстати - а ведь еще давным-давно читал что меседж WM_PAINT "имеет низший приоритет", чего же оно приходит раньше события нажатия? Может это только на Вындоуз? Ой вряд ли. Вообще в Qt 5 не знаю как посмотреть события, он как-то складывает их сначала себе а потом диспатчит из своей очереди. Это может совсем не соответствовать "событиям-первоисточникам" что послал ОС Название: Re: Очередность событий Отправлено: __Heaven__ от Апрель 14, 2015, 14:51 ИМХО, какая разница, что там - текст, не текст. Каждые 1/60 секунды вызывать таймер, который будет проверять наличие необходимости в перерисовке. Это приведёт к уменьшению рывков, возможно к ликвидации.
Название: Re: Очередность событий Отправлено: Igors от Апрель 14, 2015, 14:57 ИМХО, какая разница, что там - текст, не текст. Каждые 1/60 секунды вызывать таймер, который будет проверять наличие необходимости в перерисовке. Это приведёт к уменьшению рывков, возможно к ликвидации. Вы не можете вызывать таймер, а только получать события от него, причем они придут только если нет никаких др событий. Поэтому в примере выше таймер получите когда выполнены все 4 перерисовки Название: Re: Очередность событий Отправлено: __Heaven__ от Апрель 14, 2015, 15:07 Таймер вызывает 1 перерисовку. Даже если вы внесли 4 изменения, то они входят в эту 1 перерисовку. Поэтому он "глушиться" большим количеством перерисовок не может. Действия пользователя обрабатываются за кадром.
Название: Re: Очередность событий Отправлено: Bepec от Апрель 14, 2015, 15:16 Тут прикол в том, что перерисовка может занимать не 20 мс, а неизвестное количество времени :D
Название: Re: Очередность событий Отправлено: __Heaven__ от Апрель 14, 2015, 15:39 В упор не понимаю.
Ну пусть отрисовывается 10 секунд. Я натыкал 200 раз по окну, после перерисовки они вступают в силу на уровне мозгов. Пришло время следующей перерисовки по таймеру и эти 200 изменений появляются на экране. Я что-то не так понимаю? Название: Re: Очередность событий Отправлено: Igors от Апрель 14, 2015, 16:04 В упор не понимаю. Кто (или куда) должен прийти? Сейчас схема такая (значимые события)Ну пусть отрисовывается 10 секунд. Я натыкал 200 раз по окну, после перерисовки они вступают в силу на уровне мозгов. Пришло время следующей перерисовки по таймеру и эти 200 изменений появляются на экране. Я что-то не так понимаю? QEvent::MouseButtonPress (1) // юзер выбрал айтем, делаем update всем окнам QEvent::Paint (1) // рисуем окно 1 QEvent::Paint (2) // рисуем окно 2 ... QEvent::Paint (last) // рисуем последнее окно QEvent::MouseButtonPress (2) // юзер опять выбрал айтем, все по новой Беда в том что когда отработывает первый Paint шустрый юзер уже успел понатыкать раза 3-4. Можно отложить update и сделать его по таймеру, но минусы этого решения очевидны. Хотелось бы получить MouseButtonPress (2) сразу после QEvent::Paint (1), ведь рисовалось долго и нажатие уже состоялось. Но (хз почему) не получаю Название: Re: Очередность событий Отправлено: __Heaven__ от Апрель 14, 2015, 16:45 Хотелось бы получить MouseButtonPress (2) сразу после QEvent::Paint (1), ведь рисовалось долго и нажатие уже состоялось. Но (хз почему) не получаю То есть, нажатия пользователя проглатываются перерисовкой? Это, действительно, странноНазвание: Re: Очередность событий Отправлено: __Heaven__ от Апрель 14, 2015, 16:50 А, понял.
Дык это нормально, что нельзя вклиниться так просто между первой и второй прорисовкой, имхо. Что если между перерисовками воткнуть QCoreApplication::processEvents? Далее отслеживаем, был ли клик/тык, а там уже отменяем текущую перерисовку и начинаем всё заново. Быть может это поможет... Название: Re: Очередность событий Отправлено: Igors от Апрель 14, 2015, 17:49 Дык это нормально, что нельзя вклиниться так просто между первой и второй прорисовкой, имхо. ИМХО нет - почему более важное событие (нажатие мыши) следует после менее важного (перерисовки). Да, запрос на перерисовку (update) был послан раньше, но ведь его приоритет нижеЧто если между перерисовками воткнуть QCoreApplication::processEvents? Далее отслеживаем, был ли клик/тык, а там уже отменяем текущую перерисовку и начинаем всё заново. А как "воткнуть между" - ведь рисование это обработчик события, просить в нем еще события = верный ппцНазвание: Re: Очередность событий Отправлено: __Heaven__ от Апрель 14, 2015, 18:02 Почему вы считаете нажатие мыши более приоритетным событием, чем запрос перерисовки?
Я понимаю, что они обрабатываются в одном потоке и пока не завершится один процесс - другой не сможет вмешаться. Я вижу себе что-то вроде такого: Код
Цикл перерисовок прерывается, таймер видит, что у вас активен флаг userEvent, обнуляет его и запускает fullUpdate. Название: Re: Очередность событий Отправлено: Igors от Апрель 15, 2015, 05:46 Почему вы считаете нажатие мыши более приоритетным событием, чем запрос перерисовки? Ну как бы "впитал с молоком матери" :)Я понимаю, что они обрабатываются в одном потоке и пока не завершится один процесс - другой не сможет вмешаться. Давайте терминов придерживаться. Процесс - это тот у которого свое адресное пр-во.Так, ну с таймером все-таки получается. Вместо того чтобы сразу делать update всем окнам их надо сохранить в списке. Событие таймера извлекает указатель на окно из списка и делает ему update. А событие мыши заполняет список. Ну как-то я не в восторге. Конечно update растыкан в сотнях мест, не вижу как его глобально переопределить. И update вызывается еще и контролами Qt - тоже надо учитывать. Попробую сначала сделать пример, там посмотрим Название: Re: Очередность событий Отправлено: AlexEx от Апрель 15, 2015, 12:52 Конечно, MouseButtonPress нет, ибо GUI-шный поток один и занят в это время Paint'ом. Похоже, надо дробить Paint на части (если возможно). Аналогично тому, как иногда картинки прорисовывают - сперва одни группы точек по всей площади картинки, затем другие группы и т.д.
Название: Re: Очередность событий Отправлено: qate от Апрель 15, 2015, 13:22 0. флаг необходимости перерисовки сброшен
1. поступило событие что надо перерисовать - если флаг установлен то выход; иначе ставим флаг и таймер на 20 мсек singleshot и выход 3. таймер cработал - перерисовка, сброс флага Название: Re: Очередность событий Отправлено: Igors от Апрель 15, 2015, 14:38 Конечно, MouseButtonPress нет, ибо GUI-шный поток один и занят в это время Paint'ом. Так и следующее событие - тоже paint (теперь уже другого окна), а хотелось бы сначала pressПохоже, надо дробить Paint на части (если возможно). С OpenGL нет0. флаг необходимости перерисовки сброшен А как Вы будете рисовать в событии таймера?1. поступило событие что надо перерисовать - если флаг установлен то выход; иначе ставим флаг и таймер на 20 мсек singleshot и выход 3. таймер cработал - перерисовка, сброс флага Название: Re: Очередность событий Отправлено: qate от Апрель 15, 2015, 15:34 > А как Вы будете рисовать в событии таймера?
вот взял и рисовал на QGraphicsScene по таймеру как и описал а для OpenGL нельзя по событию таймера рисовать ? Название: Re: Очередность событий Отправлено: Igors от Апрель 15, 2015, 16:18 > А как Вы будете рисовать в событии таймера? Там мутность великая :) Надо устанавливать контекст, причем просто makeCurrent (как сделал бы нормальный человек) не катит. И контекст не будет создан до первого рисования. вот взял и рисовал на QGraphicsScene по таймеру как и описал а для OpenGL нельзя по событию таймера рисовать ? А вообще в букваре пишут что низзя, рисуйте только из paintEvent! И для обычных виджетов так и есть, не создается painter вне paintEvent. И для обычных просто так не пропустить событие рисования (отдаваясь в таймер) т.к. background уже зачищен и экран обновится "при любой погоде" Название: Re: Очередность событий Отправлено: qate от Апрель 15, 2015, 16:56 А вообще в букваре пишут что низзя, рисуйте только из paintEvent! мое рисование было - это добавление на сцену элементов сцены (additem, прямоугольники, текст, заливка) - поэтому их можно в таймере но не проблема и в paintEvent: 0. флаги "МожноРисовать" и "НужноРисовать" сброшены 1. поступило событие что надо перерисовать - если флаг "НужноРисовать" установлен то выход; иначе ставим флаг "НужноРисовать" и таймер на 20 мсек singleshot и выход 3. таймер cработал - "МожноРисовать" устанавливаем 4. в paintEvent смотрим "МожноРисовать" , если не установлен - выход. если установлен - рисуем и сбрасываем оба флага (мутексы по месту ставим) |