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

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

Страниц: 1 [2]   Вниз
  Печать  
Автор Тема: [qwt] Производительность при перерисовки графика  (Прочитано 16030 раз)
Racheengel
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 2679


Я работал с дискетам 5.25 :(


Просмотр профиля
« Ответ #15 : Январь 10, 2014, 01:03 »

Лучше рендерить долгую графику в отдельном потоке в теневой буфер и обновлять окно, только когда оно будет полностью сформировано.

а еще лучше тогда параллельно в нескольких потоках... смотря сколько ядер на целевой машине, конечно...
Но имхо лучшее решение - просто математические выкинуть ненужные точки перед рендером.
Записан

What is the 11 in the C++11? It’s the number of feet they glued to C++ trying to obtain a better octopus.

COVID не волк, в лес не уйдёт
Akon
Гость
« Ответ #16 : Январь 10, 2014, 10:45 »

Qwt 6 (как минимум) выкидывает ненужные точки (есть такая настройка). Может она делает это не самым быстрым образом? У меня точек сотни тысяч/единицы миллионов, поэтому даже сам расчет получается долгим, я полагаю.

Я даже не ставлю сейчас цели оптимизировать рисование (хотя это было бы здорово), а просто прерывать его пользовательским коллбэком. Т.е., через каждые, скажем, 10000 точек Qwt будет звать внешний коллбэк.

Половина кадра:
Покуда endPaint() не торкнули, рендеринг не начнется. Поэтому, по частям мы отрисовку наблюдать не будем.
А все эти вставки идут до endPaint(), разумеется.

 
Записан
Igors
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 11445


Просмотр профиля
« Ответ #17 : Январь 10, 2014, 11:33 »

Все таки, пока кадр не готов полностью, показывать его не стоит.
Этой проблемы нет  (double-buffer)
Записан
Old
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 4350



Просмотр профиля
« Ответ #18 : Январь 10, 2014, 11:57 »

Все таки, пока кадр не готов полностью, показывать его не стоит.
Этой проблемы нет  (double-buffer)
Вы выходите из paintEvent и не происходит обновление окна?
Покажите код вашего обработчика и назовите платформу.
Записан
Igors
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 11445


Просмотр профиля
« Ответ #19 : Январь 10, 2014, 12:45 »

Вы выходите из paintEvent и не происходит обновление окна?
Покажите код вашего обработчика и назовите платформу.
Когда прерывание обнаружено - экран еще НЕ обновлен, и я могу решить что с ним делать.

Ага, только никто не гарантирует, что скопившиеся события обработаются быстро. Улыбающийся
Нарисовали половину кадра, пользователь нажал мышь, вышли из рисовалки, пользователь увидел на экране половину картинки, а ваша программа ушла обрабатывать события... и делала это секунду (ну обработку одного из событий делал специалистпрофессионал)
Ну что же Вы выдвигаете такие "абсурдные" требования? (как Вы сами давеча говорили в др теме) Улыбающийся Это где ж видано чтобы рисовалось а события были запрещены? Вот напр Qt Dnd таких ограничений не имеет. И.т.д.  Улыбающийся

и только после этого мы вернулись и дорисовали кадр.
Ну "дорисовать" - это вряд ли, напр OpenGL рисование не инкрементально. Придется начинать все с нуля.
Записан
Old
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 4350



Просмотр профиля
« Ответ #20 : Январь 10, 2014, 13:15 »

что же Вы выдвигаете такие "абсурдные" требования? (как Вы сами давеча говорили в др теме) Улыбающийся Это где ж видано чтобы рисовалось а события были запрещены?
А в чем абсурдность и причем запрещенность событий?
Смотрите, вы вышли из paintEvent, управление вернулось в цикл обработки событий и сработал таймер, в обработчике которого мы полезли проверять обновления на сайт и длилось это действо секунду. Потом мы вернулись в цикл и перешли опять к рисованию. Вот и задержка между началом и продолжением рисования.
А что получили - непонятно? Рисовать все равно начали заново. Улыбающийся
Как я понимаю если пользователь будет клацать мышкой, программа может вообще никогда ничего не нарисовать. Улыбающийся
Записан
Igors
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 11445


Просмотр профиля
« Ответ #21 : Январь 10, 2014, 14:00 »

Как я понимаю если пользователь будет клацать мышкой, программа может вообще никогда ничего не нарисовать. Улыбающийся
Это нормально, пусть меньше клацает Улыбающийся Другое дело если операция интерактивна, обычно когда пользователь перемещает объекты мышью. Тогда нужно разрешать лишь небольшое число событий.
Записан
Old
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 4350



Просмотр профиля
« Ответ #22 : Январь 10, 2014, 14:10 »

Нормально? Ну не знаю, у нас разные представления о "нормально".
Записан
Akon
Гость
« Ответ #23 : Январь 12, 2014, 21:07 »

1. Я тут сделал следующую пробную реализацию: перекрыл QwtPlotCurve::drawSeries() с целью вызывать пользовательский коллбэк через каждые 10000 точек. Коллбэк делает следующее:
Код:
QCoreApplication::sendPostedEvents(&processingObject_, QEvent::MetaCall);
т.е. вызывает слоты некоего processingObject_, которые на данный момент имеются в очереди сообщений. Никакие другие события в очереди сообщений не обрабатываются. Вызванный т.о. слот processingObject_ в свою очередь может вызвать синхронную перерисовку другого виджета (repaint()), например, находящегося ниже по лейауту относительно QwtPlot.

Так вот, работает это несколько некорректно - не полностью или вовсе не отрисовываются другие виджеты главного окна. Я не стал разбираться. Полагаю, что причина может быть в следующем: Кьют (в моем случае) использует двойную буферизацию (backingStore) при отрисовке виджетов, а также не использует нативные контролы, т.е. сам рисует виджеты. Когда от системы приходит событие перерисовки (свернули/развернули окно, например), то если содержимое виджета не меняется, то и QWidget::paintEvent() по идее звать не нужно - в систему пойдут данные из кэша. А вот если содержимое виджета меняется (например, QLabel::setText("...")), то необходимо еще и кэш обновить. Т.е. QWidget::paintEvent() должно вызываться из контекста, связанного с этой синхронизацией. И прямой вызов repaint() одного виджета из paintEvent() другого не имеет этого контекста (не реентерабельный контекст). Но это просто поверхностное рассуждение, если кто занимался вопросом, просьба прояснить ситуацию.

2. Несколько копнул Qwt 6 на предмет отрисовки.
Например, имеется 120000 точек, шкала по оси абсцисс установлена так, что отображается только первые 10000 точек. Что делает Qwt при измененнии кривой и репаинте:
а) вне зависимости от шкалы на отрисовку спускает все 120000 точек.
б) уменьшает кол-во точек, т.к. при отрисовке большого кол-ва точек некоторые будут просто проецироваться в один и тот же пиксель. Но! При этом она чешет все 120000 вместо того, чтобы "прощупать", где начинаются видимые точки.
в) полученные точки перед отрисовкой клиппируются, т.е. в полилинии остаются те, которые соответствуют видимым 10000.
г) паинтер рисует полилинию.

Вообще, архитектура Qwt совсем небыстрая, я бы сказал в стиле Java, а не С++. Например, исключительно часто вызываемая функция QwtSeriesData::sample() виртуальная. Это как если бы в STL у нас бы был базовый интерфейс итератора с виртуальными функциями доступа к данным Улыбающийся Это удобно, но гораздо медленнее.
Записан
Igors
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 11445


Просмотр профиля
« Ответ #24 : Январь 13, 2014, 12:47 »

Так вот, работает это несколько некорректно - не полностью или вовсе не отрисовываются другие виджеты главного окна. Я не стал разбираться. Полагаю, что причина может быть в следующем: Кьют (в моем случае) использует двойную буферизацию (backingStore) при отрисовке виджетов, а также не использует нативные контролы, т.е. сам рисует виджеты. Когда от системы приходит событие перерисовки (свернули/развернули окно, например), то если содержимое виджета не меняется, то и QWidget::paintEvent() по идее звать не нужно - в систему пойдут данные из кэша. А вот если содержимое виджета меняется (например, QLabel::setText("...")), то необходимо еще и кэш обновить. Т.е. QWidget::paintEvent() должно вызываться из контекста, связанного с этой синхронизацией. И прямой вызов repaint() одного виджета из paintEvent() другого не имеет этого контекста (не реентерабельный контекст). Но это просто поверхностное рассуждение, если кто занимался вопросом, просьба прояснить ситуацию.
Сейчас у меня несколько похожие проблемы. Что мне удалось выяснить

1) Qt обеспечивает double-buffer там где ОС его не имеет (Вындоуз), иначе используется буфер ОС  (OSX). В любом случае QPainter рисует в буфере, в чем легко убедиться поставив break в paintEvent - никаких изменений на экране еще нет. Выталкивание буфера на экран происходит по окончании paint.  Важно что вызов repaint НЕ гарантирует немедленной перерисовки на всех платформах. При этом QApplication::flush никак не поможет, т.к. внутренний буфер еще не обновлен (paintEvent не было)

2) Qt часто вызывает/провоцирует paint сам вызовом update. Напр при переключении активного окна оба (новое и старое) будут перерисованы. То же самое при свертке/развертке. Избавиться от этого можно, но с трудом. Вот если таскаем окно - да, нижние не будут перерисовываться, срабатывает буфер.

3)
а также не использует нативные контролы, т.е. сам рисует виджеты
Это не одно и то же. На OSX каждому Qt контролу соответствует нативный контрол OC (т.е. используются), но рисуются они не ОС'ом, а самим Qt 

Возвращаясь к Вашим проблемам - я бы для начала проверил вызов repaint др контрола (из рисования графика). Да, это не будет работать на ОС с нативным double-buffer, ну так может это для Вас и не актуально. Если работает - то через notify отловить update (для которого не было парного paint) и после выхода из sendPostedEvents самому сделать repaint.

Все-таки оптимизация самого процесса рисования выглядит привлекательнее (то конечно легко говорить  Улыбающийся)
Записан
Akon
Гость
« Ответ #25 : Январь 13, 2014, 14:11 »

Ок. Спасибо.
Цитировать
а также не использует нативные контролы, т.е. сам рисует виджеты
Я имел ввиду, что системные дескрипторы на эти виджеты не создаются, следовательно, система о них ничего не знает и при перерисовке торкает их парента, который с дескриптором (QMainWindow?). Буду знать про MacOS.
Записан
Страниц: 1 [2]   Вверх
  Печать  
 
Перейти в:  


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