LINUX.ORG.RU

Qt, плавная анимация.


0

1

Пришёл к пониманию того, что моя дёрганная анимация (http://www.youtube.com/watch?v=KRk_LNd7EBg ) обусловлена тем, что я хочу странного от main event loop, на что он не рассчитан. Дело не в том, что в основном потоке у меня тяжёлый матан - матан вынесен в отдельные потоки, а основной поток только показывает готовые QPixmap в paintEvent(), что очень дёшево. Проблема в том, что основной цикл обработки событий объекта QApplication никому не обещал, что paintEvent() он умеет генерировать со стабильной частотой. Он имеет право иногда заниматься своими служебными вещами, блокироваться в ядре, страдать прочей фигнёй, даже если не нагружен вызовом никаких моих прочих слотов.

Что делать?

Создать отдельный поток, занимающийся только рисованием я не могу, т.к. QWidget::paintEvent() может быть вызвана только из основного цикла обработки событий QApplication (или нет?). Хотя можно создавать альтернативные циклы обработки событий в альтернативных потоках, но я не знаю, может ли быть из альтернативных ц.о.с. вызываться paintEvent... Мне кажется, paintEvent() должен вызваться из того ц.о.с., с которым ассоциирован синглтонный объект QApplication. Да или нет?

Неужели надо браться за OpenGL, если оставаться в рамках Qt? Рисовать не через OpenGL, а тем же способом, каким рисуются виджеты, но в обход Qt наверное тоже можно, но это будет совсем грязный хак.

★☆

Последнее исправление: kiverattes (всего исправлений: 1)

Ответ на: комментарий от MikeDM

Вынесена с самого начала, причём в 8 потоков. Основной поток всегда имеет уже наперёд готовую кучу QPixmap-ов, которые тупо показывает в paintEvent(). Это очень дешёвая операция - показать готовые QPixmap в paintEvent(). В основном потоке нет математики.

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

ну а действительно, в чем проблема показывать OpenGL фрейм?

ЗЫ я в теме, что ты просишь не секу, поэтому рассуждаю в меру способностей =)

MikeDM ★★★★★
()

C какая у тебя частота обновления? Синхронизируй изменения экрана с реальным временем. то есть если пропустишь фрейм, но общая картинка будет идти плавно, это будет намного менее заметно на глаз, чем если отрисовывать «просроченные» фреймы.

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

У меня есть только paintEvent(), а когда он вызовется - я контролировать не могу, а вне его ничего нарисовать нельзя.

kiverattes ★☆
() автор топика

Тебе правильно сказали, синхронизируй с часами реального времени. Твоя задача в функции рисования не «показывать готовый кадр». А «нарисовать именно то в кадре, что должно там быть сейчас по часам».

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

За временем следит QAbstractAnimation, которая создана для этого. Она пользуется мегаточными часами и по ним в нужные моменты времени аптейдит смещение рисования. То есть, в любой момент вызова paintEvent() все параметры отображения соответствуют времени.

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

Ты сказал, что подставляешь готовый кадр, а подстановка производится в случайный момент времени (время вызова paintEvent в общем случае не определено). Не так? Где я тебя неправильно понял?

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

Кадр подготавливается не в paintEvent(). Можно сказать, что кадр вообще не подготавливается, ибо кадр - это отображение готового QPixmap с нужного смещения. Меняется только смещение, а меняется оно с помощью QPropertyAnimation.

kiverattes ★☆
() автор топика
Ответ на: комментарий от devpony

С ним та же байдень. Да ещё он на винде какой-то неточный, QPropertyAnimation поточнее.

kiverattes ★☆
() автор топика

Короче, я осознал фундаментальную проблему, из-за которое решение моей задачи принципиально невозможно без хитрого динамического анти-алиасинга самих картинок и без вычисления координат в double. И OpenGL мне не поможет и даже если я припаяю провод синхронизации развёртки монитора прямо к моему paintEvent() - будет тоже ноль эффекта.

Всё у меня, короче, зашибись, плакать можно заканчивать, проблемы нет, есть особенность алгоритма.

kiverattes ★☆
() автор топика
Последнее исправление: kiverattes (всего исправлений: 3)
Ответ на: комментарий от geekless

Проблема глубже - в целочисленном вычислении движения пикселей.

kiverattes ★☆
() автор топика
Ответ на: комментарий от I-Love-Microsoft

Посмотрите видео каким-нибудь способом, чтобы само воспроизведение видео не накладывало сверху своих глюков. Скачайте видео с ютуба и посмотрите компом без тиринга. Там всё вроде как видно: прокатывается волна резкого смещения вперёд снизу вверх. Но, как я уже писал, проблема не в Qt, а в целочисленных вычислениях. Ошибки квантования временного континуума, мать его! Чтобы побороть, надо переходить на real-number-координаты и антиалиасинг.

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

антиалиасинг.

А последнее зачем? Не любишь лесенку на полигонах?

pathfinder ★★★★
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.