LINUX.ORG.RU

Регулярная автоматическая перерисовка (анимация?) в PyQt5?

 ,


0

1

Сабж.

Есть окно с картинкой. При некоторых условиях (кажем галочка в чекбоксе) надо автоматически обновлять картинку с каким то интервалом времени. В интервалах между обновлениями окно не должно блокироваться, т.е. должны работать все виджеты и пр. Если галочку сняли, автоматическое обновление должно прекратится.

Картинка строится через QPainter.

Как это сделать Ъ? Qt и PyQt знаю очень плохо.

★★★★★

В интервалах между обновлениями окно не должно блокироваться, т.е. должны работать все виджеты и пр

Это возможно только в определённых пределах. В Qt4-5, насколько я помню, весь GUI работает в одном процессе. То есть ограничено производительностью вашего камня (не того, который щебень, а того, который CPU ). Так что Вам всё-же придётся ограничить либо размер картинки, либо частоту её обновления.

Так что, в разумных пределах метода два:

  1. Вызывать ProcessMessages в вашем цикле обновления картинки.
  2. Использовать QTimer и обновлять картинку через него. Код внутри обработчика QTimer должен быть быстрым, иначе будут тормоза.
pup_kin
()
Последнее исправление: pup_kin (всего исправлений: 1)

Qt и PyQt знаю очень плохо.

PyQt не надо. Бери PySide, это официальный биндинг от разрабов Qt

pup_kin
()
Ответ на: комментарий от pup_kin

Использовать QTimer и обновлять картинку через него. Код внутри обработчика QTimer должен быть быстрым, иначе будут тормоза.

Картинку нужно рендерить в отдельном потоке, насколько это позволяют используемые средства. Обработчик QTimer должен запрашивать картинку, и, если та готова, атомарно заменять картинку, подаваемую на отрисовку, на свежеотрендеренную. Так, по крайней мере, можно будет писать гневные сообщения в stderr в случае тормозов.

В общем, двойная буферизация на коленке.

Siborgium ★★★★★
()
Последнее исправление: Siborgium (всего исправлений: 1)
Ответ на: комментарий от Siborgium

ЯННП. Во времена моей молодости (не в Qt) скажем было событие OnIdle. В PyQt я сходу че то не нашел такого.

Вариант с QTimer-ом тоже рабочий, я так понимаю он вызывает какой то обработчик? В принципе этот обработчик может смотреть в очередь заданий, если задание пришло то он его выполняет. Задание на перерисовку перерисовывает картинку и ставит в очередь следующее задание. Как то так…

AntonI ★★★★★
() автор топика
Ответ на: комментарий от Siborgium

Понятно, что длительные вычисления нужно делать в отдельном потоке.

Но я имел в виду, нагрузку, специфичную для GUI. Можно сколько угодно делать картинок в фоне, но быстродействие GUI-потока всё равно фундаментально ограничено частотой ЦП ( ну и быстродействием самих библиотек ГПИ, и графической подсистемы ОС ).

pup_kin
()
Ответ на: комментарий от AntonI

я так понимаю он вызывает какой то обработчик?

Да, конечно! В главном цикле QApplication вызывается код QTimer и уже из него Ваш обработчик и его код.

pup_kin
()
Последнее исправление: pup_kin (всего исправлений: 1)
Ответ на: комментарий от AntonI

он вызывает какой то обработчик? В принципе этот обработчик может смотреть в очередь заданий, если задание пришло то он его выполняет.

Не следует так делать. Что, если выполнение задания занимает больше времени, чем промежуток между срабатываниями таймера?

Задание на перерисовку перерисовывает картинку и ставит в очередь следующее задание.

При таком подходе тормоза будут просто по определению, потому что когда таймер пришел и картинку уже надо показать, она только начинает рендериться.

Нужно держать две картинки, одна из которых показывается на экране, а на вторую рисуется новое содержимое. Когда приходит таймер, первая заменяется второй, если с прошлого прихода таймера вторая изменилась.

Siborgium ★★★★★
()
Ответ на: комментарий от Siborgium

Нужно держать две картинки, одна из которых показывается на экране, а на вторую рисуется новое содержимое. Когда приходит таймер, первая заменяется второй, если с прошлого прихода таймера вторая изменилась.

Наиценнейшее замечание!

В принципе этот обработчик может смотреть в очередь заданий, если задание пришло то он его выполняет. Задание на перерисовку перерисовывает картинку и ставит в очередь следующее задание.

Картинку нужно рендерить в отдельном потоке, насколько это позволяют используемые средства

Вместе с предыдущей идеей это уже можно считать отличной архитектурной идеей! Осталось только закодировать, загитхабить и написать статью в бложике.

Браво! Котаны! Браво!

pup_kin
()
Последнее исправление: pup_kin (всего исправлений: 2)
Ответ на: комментарий от Siborgium

Что, если выполнение задания занимает больше времени, чем промежуток между срабатываниями таймера?

Ничего. Обработчик видит что очередь пустая и ничего не делает. Тут важно именно не запустить лишнюю отрисовку если предыдущая еще не прошла.

когда таймер пришел и картинку уже надо показать, она только начинает рендериться.

Это не страшно. Да собственно новая картинка выбрасывается на экран только после того как она полностью готова, т.е. двойная буферизация у меня уже есть в текущей версии кода;-)

AntonI ★★★★★
() автор топика
Последнее исправление: AntonI (всего исправлений: 1)
Ответ на: комментарий от pup_kin

Картинку нужно рендерить в отдельном потоке, насколько это позволяют используемые средства

Эммм… можно считать что не позволяют. В общем это не является проблемой которую тут надо обсуждать (реально картинка рендерится в плюсах на CPU на всех ядрах которые есть, или на GPU если GPU есть).

написать статью в бложике.

Статьи я пишу на другие темы и не в бложик;-)

AntonI ★★★★★
() автор топика
Последнее исправление: AntonI (всего исправлений: 1)
Ответ на: комментарий от AntonI

Статьи я пишу на другие темы и не в бложик;-)

О боже мой! Господин начальник! Простите меня! Я так больше не буду!

pup_kin
()
Ответ на: комментарий от pup_kin

Смиррна-вооольнааа-рррразойдись!;-)

PS глянул резюме - какие именно уравнения Вы решали?

AntonI ★★★★★
() автор топика
Последнее исправление: AntonI (всего исправлений: 1)
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.