Прерывистая прокрутка QPixmap с использованием Qt Animation Framework

Я создал QPropertyAnimation и подключил его к своему SonogramWidget, который прокручивает длинную картинку вертикально по событиям анимации. «Длинная картинка» состоит из 100 предварительно рассчитанных объектов QPixmap размером 1024x128, расположенных друг за другом по вертикали. Они отображаются в SonogramWidget::paintEvent() с QPainter. Процедура рисования рисует не все QPixmap сразу, а только видимые из них, учитывая высоту виджета и текущее вертикальное смещение. Процессор почти свободен, потому что QPixmap — самый быстрый способ отображения картинки. При прокрутке нет больших вычислений, потому что все 100 QPixmaps предварительно вычисляются и сохраняются в памяти.

Я вижу странный эффект: пульсирующее движение: 2 раза в секунду все изображение немного ускоряется и перемещается вверх на 1..2 пикселя быстрее, чем обычное движение. Тот же эффект, когда я заменяю Qt Animation Framework одним QTimer со скоростью 60 кадров в секунду и прокручиваю изображение в его слоте.

Видео: http://www.youtube.com/watch?v=KRk_LNd7EBg#t=8 (смотреть с 00:08; мой firefox добавляет больше обрезания к самому воспроизведению видео, google chrome воспроизводит видео намного лучше).

Я вижу тот же эффект для моей сборки Linux и Windows.

РЕШЕНИЕ Я разобрался с проблемой: "обрезка" была не ошибкой, а функцией! Это особенность вычисления целых чисел, поэтому иногда нам приходилось использовать разные числа для анимации, например: 16,16,16,16,16,16,17,16,16,16,16,16,17,. ...


person pavelkolodin    schedule 30.08.2013    source источник
comment
Что говорит ваша загрузка процессора? Прокрутка становится медленнее, чем больше видно «белого». Поскольку для QPainter не должно иметь значения, является ли рисуемый пиксель белым или черным, это должно быть что-то с вашими вычислениями. Если ваша машина близка к своему пределу, я ожидаю странных выходных артефактов, подобных этому. Или это «медленнее» — оптическая иллюзия? Не уверен.   -  person Greenflow    schedule 30.08.2013
comment
Все QPixmaps предварительно вычисляются и сохраняются в памяти. Никаких вычислений во время прокрутки. При использовании только черных пикселей все изображение становится менее контрастным, и мы не замечаем описанного эффекта.   -  person pavelkolodin    schedule 30.08.2013
comment
Понятия не имею, так что это чистое предположение. Но иногда даже это помогает. :-) Итак, можно ли поместить все в одну растровую карту? Только временно? Просто чтобы исключить, что 100 вертикальных QPixmap каким-то образом странно взаимодействуют?   -  person Greenflow    schedule 30.08.2013
comment
Несмотря на то, что изображения QPixmap предварительно вычисляются, вы копируете видимые изображения в событии paintEvent SonogramWidget, не так ли? Если да, то можете ли вы опубликовать этот код?   -  person TheDarkKnight    schedule 30.08.2013
comment
Гадание @Greenflow - это то, что мне нужно! Я попробовал это и, насколько я помню, увидел тот же эффект, поэтому отказался от этой стратегии.   -  person pavelkolodin    schedule 30.08.2013
comment
@ Merlin069 текущий код содержит много деталей, поэтому я боюсь, что его будет трудно прочитать. Я попытаюсь создать отдельный проект только для того, чтобы воспроизвести этот описанный эффект позже.   -  person pavelkolodin    schedule 30.08.2013
comment
Обратите внимание, что функция рисования должна быть максимально оптимальной и иметь дело только с рисованием на экране. Если это не так в вашем проекте, это может объяснить проблемы, которые вы видите.   -  person TheDarkKnight    schedule 30.08.2013
comment
Рисование и обновление в какой-то момент всегда запускается циклом событий. Я предполагаю, что есть какое-то другое событие, которое срабатывает через регулярные промежутки времени и немного изменяет время выполнения вашей процедуры рисования.   -  person Greenflow    schedule 30.08.2013
comment
@Greenflow Итак, вы предполагаете, что QPropertyAnimation работает в том же цикле событий, который используется для обработки всех моих событий, и иногда этот цикл событий слишком занят, чтобы обеспечить необходимую «галочку» для QPropertyAnimation? Могу ли я создать независимый цикл событий специально для QPropertyAnimation?   -  person pavelkolodin    schedule 30.08.2013
comment
Может быть, это ерунда, что я говорю. Но я бы не стал связывать это с QPropertyAnimation. В какой-то момент ваш QPixmap должен быть нарисован на вашем виджете. Это вызывается событием paintEvent. Если теперь это paintEvent не приходит регулярно, например. каждые x мс оно приходит на несколько мс позже, потому что что-то еще в основном цикле обработки событий задержало его выполнение. Я не знаю, большой или малой должна быть эта задержка, чтобы ее можно было увидеть. Но к некоторым вещам наши глаза раздражающе чувствительны. У Мерлина, кажется, больше опыта в этой области.   -  person Greenflow    schedule 30.08.2013
comment
@Greenflow, о, понятно. paintEvent() вызывается в основном цикле QApplication, и я не могу переместить вызов paintEvent() в другой независимый «основной цикл»?   -  person pavelkolodin    schedule 30.08.2013
comment
Я не думаю, что это возможно. По крайней мере я не знаю как. Создать новый цикл событий легко, но я не думаю, что вы можете использовать его для доставки paintEvents вместо основного цикла событий. Вот хорошее описание системы событий Qt: doc.qt.digia.com /qq/qq11-events.html. И будьте осторожны с моей попыткой объяснить вашу проблему. Общая идея, конечно, не ошибочна, но эффект может быть слишком мал, чтобы быть реальной причиной вашей проблемы.   -  person Greenflow    schedule 30.08.2013
comment
Извините, что поздно отвечаю - я только что получил уведомление о комментариях. Хотя вы не можете переместить какой-либо код, связанный с рисованием, в другой поток, вы можете переместить весь остальной код. Опять же, не видя вашего кода, трудно что-либо сделать, кроме как дать общие предложения. Однако, если у вас есть какой-либо код, работающий в основном потоке, который не выполняет рендеринг, вы можете попробовать перенести его в другой QThread, но убедитесь, что используете QThread правильно: mayaposch.wordpress.com/2011/11/01/   -  person TheDarkKnight    schedule 03.09.2013
comment
@ Merlin069 Merlin069 Я понял проблему: измельчение было не ошибкой, это была функция! :) Это особенность вычисления целых чисел, поэтому иногда нам приходилось использовать разные числа для анимации, например: 16,16,16,16,16,16,17,16,16,16,16,16,17 , ....   -  person pavelkolodin    schedule 03.09.2013
comment
Ха, я рад это слышать. Как я уже говорил, Qt может быть великолепен при правильном использовании ;O)   -  person TheDarkKnight    schedule 03.09.2013


Ответы (1)


В paintEvent добавьте следующее утверждение:

Q_ASSERT(m_animation->currentValue() == m_animatedPropertyValue);

Если он срабатывает, то вы знаете, что должны использовать currentValue() вместо значения свойства. Возможно, это так. Дайте мне знать.

person Kuba hasn't forgotten Monica    schedule 30.08.2013