Russian Qt Forum

Qt => Model-View (MV) => Тема начата: andrew.k от Июль 24, 2012, 13:43



Название: Анимация в делегате
Отправлено: andrew.k от Июль 24, 2012, 13:43
Как такое реализовать красиво?


Название: Re: Анимация в делегате
Отправлено: Bepec от Июль 24, 2012, 13:45
QPropertyAnimation ты и сам знаешь, думаю.

А что именно хочешь красивого? появление/изменение/отображение?


Название: Re: Анимация в делегате
Отправлено: andrew.k от Июль 24, 2012, 14:03
QPropertyAnimation ты и сам знаешь, думаю.

А что именно хочешь красивого? появление/изменение/отображение?
Я боялся, что ты ответишь :)


Название: Re: Анимация в делегате
Отправлено: andrew.k от Июль 24, 2012, 14:05
Посмотри внимательно на название темы.

А что именно хочешь красивого? появление/изменение/отображение?
Нужна не анимация красивая, а красивая реализация, т.к. корявое решение худо-бедно можно выдумать.


Название: Re: Анимация в делегате
Отправлено: Bepec от Июль 24, 2012, 14:09
Ну тогда тебе такой ответ - наиболее красиво будет со своей отрисовкой.

Наиболее незатратно - QPropertyAnimation.

PS что анимировать то собрался?


Название: Re: Анимация в делегате
Отправлено: andrew.k от Июль 24, 2012, 14:13
Ну тогда тебе такой ответ - наиболее красиво будет со своей отрисовкой.

Наиболее незатратно - QPropertyAnimation.
Лицо рука.


Название: Re: Анимация в делегате
Отправлено: andrew.k от Июль 24, 2012, 14:18
Нашел статью (http://www.diotavelli.net/PyQtWiki/Animated%20items%20using%20delegates%20and%20movies) на эту тему.
Но не понимаю по-питонски.

Хотелось бы понять концепцию. На сколько я понял автор вызывает, update у вьюхи, заставляя её целиком перерисовываться.
Если так, то это грустный метод.


Название: Re: Анимация в делегате
Отправлено: andrew.k от Июль 24, 2012, 14:35
Нашел еще (http://www.prog.org.ru/topic_12294_0.html) одного такого же мученика. Читаю.


Название: Re: Анимация в делегате
Отправлено: Bepec от Июль 24, 2012, 14:41
Интересно. Ток название надо было чуть подробнее - как сделать анимированную картинку в делегате :) А то анимации в мире много.

Как своё могу предложить просто отдавать в модели картинку, меняющуюся по таймеру. А другие способы вон в последней теме вроде описаны.



Название: Re: Анимация в делегате
Отправлено: andrew.k от Июль 24, 2012, 14:49
Интересно. Ток название надо было чуть подробнее - как сделать анимированную картинку в делегате :) А то анимации в мире много.
я тебе даже сказал: "перечитай название темы". Но тебе нужно написать хоть что-нибудь, даже не разбираясь в смысле ни проблемы, ни тобой написанного.
Впрочем как всегда.

А другие способы вон в последней теме вроде описаны.
О! Спасибо за наводку! Реально помог.


Название: Re: Анимация в делегате
Отправлено: andrew.k от Июль 24, 2012, 15:39
Вывод такой: делегат не способен отображать анимацию (что в общем-то было понятно сразу).

Придумал такую концепцию: анимацией будет все-таки управлять модель. А а уже дело делегата рисовать анимацию или нет.
Поэтому без этой связки не обойтись. Соответственно модель при возникновении анимации будет отправлять периодически dataChanged, чтобы делегат имел возможность перерисовать ячейку. Тут ничего необычного в общем.
Теперь фокус. Т.к. в моей модели не используется колонка в индексе, то можно использовать ее для передачи флага от модели к делегату. По этому флагу делегат может определить нужна ли отрисовка целиком ячейки, либо только анимированной части.
Это даст выигрыш в производительности в случае если метод paint сильно нагружен и если сразу много анимированных ячеек.

Можно извратиться еще больше и использовать отрицательный значения в индексе. Но это уже хз. Возможно приведет к каким-нибудь трудностям.

Пока это только теория. Буду пробовать.


Название: Re: Анимация в делегате
Отправлено: vregess от Июль 24, 2012, 16:53
ИМХО это бредовая идея - перекладывать на модель анимацию. Ведь модель по сути не изменяет свое состояние?
Отображением должен заниматься View (и делегаты).
Я бы посоветовал сделать какой-нить QTimedView в котором есть таймер, API для регистрации делегатов с анимацией.
По таймауту пинать делегатов. Такая вот общая идея.


Название: Re: Анимация в делегате
Отправлено: Bepec от Июль 24, 2012, 17:10
Тогда уж вообще пойдём в крайность - создать класс, выводящий анимацию по координатам, получаемым от делегатов :D


Название: Re: Анимация в делегате
Отправлено: andrew.k от Июль 24, 2012, 17:15
Тогда уж вообще пойдём в крайность - создать класс, выводящий анимацию по координатам, получаемым от делегатов :D
Я же тебя уже поблагодарил за посильную помощь.


Название: Re: Анимация в делегате
Отправлено: andrew.k от Июль 24, 2012, 17:23
ИМХО это бредовая идея - перекладывать на модель анимацию. Ведь модель по сути не изменяет свое состояние?
Не особенно бредовая, в условиях необходимости, имхо. По сути да не меняет.
Представь что это модель состояний каких-нибудь датчиков, где в одной из колонок меняется параметр, есть сигнал-нет сигнала. Состояние меняется часто.
А делегат рисует данные двух колонок в одной :o В итоге видим анимацию.

Я бы посоветовал сделать какой-нить QTimedView в котором есть таймер, API для регистрации делегатов с анимацией.
По таймауту пинать делегатов. Такая вот общая идея.
Ты не можешь пинать делегатов, ты можешь пинать только вьюху, а вьюха пинает делегатов. Это раз.
Обновить ты можешь только ячейку, а если код отрисовки громоздкий, то это потеря производительности. Это два.

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


Название: Re: Анимация в делегате
Отправлено: vregess от Июль 24, 2012, 22:35
Не особенно бредовая, в условиях необходимости, имхо. По сути да не меняет.
Представь что это модель состояний каких-нибудь датчиков, где в одной из колонок меняется параметр, есть сигнал-нет сигнала. Состояние меняется часто.
А делегат рисует данные двух колонок в одной :o В итоге видим анимацию.
Смотря на заголовок топика я представляю себе таблицу, где в некоторых ячейках нарисована звезда, которая изредка бликует.

Цитата: andrew.k
Ты не можешь пинать делегатов, ты можешь пинать только вьюху, а вьюха пинает делегатов. Это раз.
Это и имелось ввиду.

Цитата: andrew.k
Обновить ты можешь только ячейку, а если код отрисовки громоздкий, то это потеря производительности. Это два.

Похоже это связано с
Цитата: andrew.k
Теперь фокус. Т.к. в моей модели не используется колонка в индексе, то можно использовать ее для передачи флага от модели к делегату. По этому флагу делегат может определить нужна ли отрисовка целиком ячейки, либо только анимированной части.
Это даст выигрыш в производительности в случае если метод paint сильно нагружен и если сразу много анимированных ячеек.

Что мешает в нем закешировать тяжелую графику...
И зачем использовать " колонку в индексе", если есть роли - передавай там флаг.

Цитата: andrew.k
Если готов обсуждать этот вопрос, прочти тему по последней ссылке, а то повторяем то, что и так ясно. И если будет, что добавить милости просим.

Да, я перечитал топик. И остался при своем мнении.
Как бы я сделал:
1) Делаем свой View на базе нужного:
* запускаем таймер и ловим таймаут в onAnimationTimeout()
* добавляем метод регистрации элементов модели (используя индекс), где нужна анимация

Код:
// Псевдокод
void MyView::onAnimationTimeout()
{
    foreach (registered index)
    {
        if (index is visible)
        {
           delegate = itemDelegate(index);
           delegate->setDrawAnimation(true);
           update(index);
        }
    }
}

2) Делаем базовый делегат для анимации с методами setDrawAnimation(bool)/isDrawAnimation().
В методе paint() что-нибудь подобное:

Код:
  if (isDrawAnimation())
    // обновляем анимацию и сбрасываем флаг анимации
  else
    // рисуем, используя данные из модели


Название: Re: Анимация в делегате
Отправлено: andrew.k от Июль 25, 2012, 11:31
Не особенно бредовая, в условиях необходимости, имхо. По сути да не меняет.
Представь что это модель состояний каких-нибудь датчиков, где в одной из колонок меняется параметр, есть сигнал-нет сигнала. Состояние меняется часто.
А делегат рисует данные двух колонок в одной :o В итоге видим анимацию.
Смотря на заголовок топика я представляю себе таблицу, где в некоторых ячейках нарисована звезда, которая изредка бликует.
Ну, например, так.

Цитата: andrew.k
Обновить ты можешь только ячейку, а если код отрисовки громоздкий, то это потеря производительности. Это два.

Похоже это связано с
Цитата: andrew.k
Теперь фокус. Т.к. в моей модели не используется колонка в индексе, то можно использовать ее для передачи флага от модели к делегату. По этому флагу делегат может определить нужна ли отрисовка целиком ячейки, либо только анимированной части.
Это даст выигрыш в производительности в случае если метод paint сильно нагружен и если сразу много анимированных ячеек.

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

И зачем использовать " колонку в индексе", если есть роли - передавай там флаг.
Затем, чтобы делегат различал два события. Обновление айтема или обновление только кадра анимации. Через роли этого не добиться.

Цитата: andrew.k
Если готов обсуждать этот вопрос, прочти тему по последней ссылке, а то повторяем то, что и так ясно. И если будет, что добавить милости просим.

Да, я перечитал топик. И остался при своем мнении.
Как бы я сделал:
1) Делаем свой View на базе нужного:
* запускаем таймер и ловим таймаут в onAnimationTimeout()
* добавляем метод регистрации элементов модели (используя индекс), где нужна анимация

2) Делаем базовый делегат для анимации с методами setDrawAnimation(bool)/isDrawAnimation().

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


Название: Re: Анимация в делегате
Отправлено: vregess от Июль 25, 2012, 14:27
Цитата: andrew.k
И кстати тоже отдельный вопрос, как бы ты реализовывал кеширование в делегате?
Что-нибудь такое: QMap<QModelIndex,QPixmap>

Цитата: andrew.k
Затем, чтобы делегат различал два события. Обновление айтема или обновление только кадра анимации. Через роли этого не добиться.
Не совсем ясно, почему не добиться.

Цитата: andrew.k
Не понял, когда ты планируешь переключать делегат в обычный режим.

Цитировать
if (isDrawAnimation())
    // обновляем анимацию и сбрасываем флаг анимации

Хотя это можно сделать в методе onAnimationTimeout()
Код:
// Псевдокод
void MyView::onAnimationTimeout()
{
    foreach (registered index)
    {
        if (index is visible)
        {
           delegate = itemDelegate(index);
           delegate->setDrawAnimation(true);
           update(index);
           delegate->setDrawAnimation(false); // вот тут
        }
    }
}

Цитата: andrew.k
В тот момент когда ты переключишь делегат в режим рисования анимации, может потребоваться полная отрисовка айтема, а у тебя делегат в режиме анимации. И привет.

Тут я не совсем уверен, как работает update() у View (есть ли там какие-нибудь оптимизации по количеству вызовов), но по идее все это будет происходить последовательно. И даже если надо будет отрисовать анимацию и обновление модели, то произойдет это последовательно, тк выполняется в одном потоке в одном цикле сообщений.


Название: Re: Анимация в делегате
Отправлено: andrew.k от Июль 25, 2012, 16:16
Цитата: andrew.k
И кстати тоже отдельный вопрос, как бы ты реализовывал кеширование в делегате?
Что-нибудь такое: QMap<QModelIndex,QPixmap>
Ок.

Цитата: andrew.k
Затем, чтобы делегат различал два события. Обновление айтема или обновление только кадра анимации. Через роли этого не добиться.

Не совсем ясно, почему не добиться.
Потом что делегат не сможет определить, кто инициировал событие отрисовки.
Ты предлагаешь переключать флаг в модели, но в этот момент кто-то подвинул окно или развернул и делегат собрался рисовать, а у тебя в модели флаг анимации.
А передавая флаг в индексе, делегат всегда будет точно знать что нужно рисовать, т.к. индекс, который передаст вьюха будет без колонки (c == 0)

Цитата: andrew.k
Не понял, когда ты планируешь переключать делегат в обычный режим.
Теперь понял.

Тут я не совсем уверен, как работает update() у View (есть ли там какие-нибудь оптимизации по количеству вызовов), но по идее все это будет происходить последовательно. И даже если надо будет отрисовать анимацию и обновление модели, то произойдет это последовательно, тк выполняется в одном потоке в одном цикле сообщений.
Есть. Update (http://qt-project.org/doc/qt-4.8/qwidget.html#update) не выполняет мгновенной перерисовки, а лишь добавляет событие в очередь.
И теоретически может так случиться, что оно придет позже или раньше, чем ты ожидаешь.


Название: Re: Анимация в делегате
Отправлено: vregess от Июль 25, 2012, 16:24
Цитировать
Есть. Update не выполняет мгновенной перерисовки, а лишь добавляет событие в очередь.
И теоретически может так случиться, что оно придет позже или раньше, чем ты ожидаешь.

void QAbstractItemView::update ( const QModelIndex & index ) != void QWidget::update ()


Название: Re: Анимация в делегате
Отправлено: andrew.k от Июль 25, 2012, 17:07
Цитировать
Есть. Update не выполняет мгновенной перерисовки, а лишь добавляет событие в очередь.
И теоретически может так случиться, что оно придет позже или раньше, чем ты ожидаешь.

void QAbstractItemView::update ( const QModelIndex & index ) != void QWidget::update ()
Согласен, но думаю работают они одинаково.


Название: Re: Анимация в делегате
Отправлено: vregess от Июль 25, 2012, 18:30
Согласен, но думаю работают они одинаково.

Посмотрел исходники - да, внутри вызывается QWidget::update().
Ну тогда надо заменить на repaint():

Код:
// Псевдокод
void MyView::onAnimationTimeout()
{
    foreach (registered index)
    {
        if (index is visible)
        {
           delegate = itemDelegate(index);
           delegate->setDrawAnimation(true);
           const QRect& rect = visualRect(index);
           repaint(index);
        }
    }
}


Название: Re: Анимация в делегате
Отправлено: andrew.k от Июль 25, 2012, 18:34
Согласен, но думаю работают они одинаково.

Посмотрел исходники - да, внутри вызывается QWidget::update().
Ну тогда надо заменить на repaint():

Код:
// Псевдокод

           repaint(index);
        }
    }
}
Нет такого метода и даже если был, это не круто было бы.


Название: Re: Анимация в делегате
Отправлено: andrew.k от Июль 25, 2012, 18:37
На данный момент я отказался от этой идеи, но потом в научных целях попробую реализовать.

Пока можно просто пообсуждать)


Название: Re: Анимация в делегате
Отправлено: vregess от Июль 25, 2012, 19:45
Нет такого метода и даже если был, это не круто было бы.

ошибся, надо repaint(rect);


Название: Re: Анимация в делегате
Отправлено: andrew.k от Июль 25, 2012, 19:49
Нет такого метода и даже если был, это не круто было бы.

ошибся, надо repaint(rect);
не круто  ;)


Название: Re: Анимация в делегате
Отправлено: andrew.k от Июль 26, 2012, 11:10
Цитата: andrew.k
И кстати тоже отдельный вопрос, как бы ты реализовывал кеширование в делегате?
Что-нибудь такое: QMap<QModelIndex,QPixmap>
Со временем такой кеш будет разрастаться.
Например, модель была вообще очищена, а кеш продолжает хранить.
Как очищать его от неиспользуемых элементов?


Название: Re: Анимация в делегате
Отправлено: vregess от Июль 27, 2012, 11:02
Можно ловить сигнал удаления элементов в делегате, но боюсь для тебя это не слишком крутое решение.


Название: Re: Анимация в делегате
Отправлено: Bepec от Июль 27, 2012, 14:16
Вы б лучше сделали :D А там уже критики найдутся :D

PS я тоже хочу анимированные гифки в model-view!


Название: Re: Анимация в делегате
Отправлено: andrew.k от Июль 27, 2012, 14:34
Вы б лучше сделали :D А там уже критики найдутся :D

PS я тоже хочу анимированные гифки в model-view!
Так вперед:
Цитировать
Ну тогда тебе такой ответ - наиболее красиво будет со своей отрисовкой.

Наиболее незатратно - QPropertyAnimation.

Или ты только советовать можешь?


Название: Re: Анимация в делегате
Отправлено: Bepec от Июль 27, 2012, 15:01
Утятя ) Твоя инициатива. А инициатива всегда и.... использует инициатора :D