Russian Qt Forum

Qt => Model-View (MV) => Тема начата: neosapient от Февраль 02, 2010, 13:30



Название: Помогите организовать мигание иконки внутри делегата
Отправлено: neosapient от Февраль 02, 2010, 13:30
Здравствуйте.

Есть собственная модель, которая отображается в TableView. Вместе они образуют таблицу, в которой надо прикрутить столбец alarm.

То есть при наступлении определенного момента, в столбец alarm начинает мигать иконка. И мигает она до тех пор, пока на неё не кликнут.

Предполагаю, что придеться писать свой собственный делегат, который позволит организовать мигание.
Вижу несколько задач:
1) Определиться с тем, как должна выглядеть модель с данными.
2) Определиться с тем, как информировать компоненты программы о старте мигания.
3) Разработать делегат, который будет самостоятельно управлять миганием
4) Так же делегат должен реагировать на команду старта мигания и отлавливать клик мыши, для стопа  мигания.


Как я вижу пункты 1 и 2: в мою модель я могу добавить ещё один столбец. По умолчанию, в слотбце будет находиться значение 0. Как только произойдет alarm-событие, то в этой ячейке 0 смениться на 1. Далее делегат, при значении 1 должен начать мигание, а значение ячейки перевести в состояние 2. В тот же момент должен быть запущен "таймер", который задаст такт мигания.
Вот тут для меня начинается путаница. Либо таймер должен поднимать/сбрасывать какой то флаг, а делегат всего лишь отображает иконку в одном из состояний флага. Либо "таймер" должен посылать сигналы делегату с указанием, что тот должен отображать. Либо мигание следует положить на плечи самого делегата и изменять модель с данными лучше не следует....

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



Название: Re: Помогите организовать мигание иконки внутри делегата
Отправлено: Павел_F. от Февраль 02, 2010, 19:22
В столбце отобразить иконку( возвращать в зависимости от значения нужный пиксмап через data по Qt::DecorationRole). В модели сделать таймер и по нему в setData менять значение. И без делегата иконка будет меняться, стоит лишь запустить таймер.


Название: Re: Помогите организовать мигание иконки вн&#
Отправлено: neosapient от Февраль 03, 2010, 18:39
Цитировать
В столбце отобразить иконку( возвращать в зависимости от значения нужный пиксмап через data по Qt::DecorationRole). В модели сделать таймер и по нему в setData менять значение. И без делегата иконка будет меняться, стоит лишь запустить таймер.

Практически так и сделал.
Запустил QTimeLine в режиме "меандра". В моделе создал массив флагов. В QAbstractTableModel::data() проверяю отдаваемые значения. Если оно является "опасным", то в массиве устанавливается соответствующий флаг. Настроил QTimeLine  отсылать сигнал dataChanged() два раза в секунду. Когда TableView запрашивает значение в мигающем столбце,  QAbstractTableModel::data()  возвращает картинку при сочетании трех условий: 1) сейчас "опасное" значение 2) никто не кликал по мигающей ячейке 3) сейчас такт QTimeLine, при котором следует показать иконку.
Оно работает...

Но в моем представлении, модель не должна управлять "анимацией" в делегате. Поэтому хочу понять, как правильно разделить модель и анимацию. В идеале я должен подставлять 0 или 1, а делегат должен осуществлять анимацию, а так же отсылать к QTableView сигнал о необходимости обновить подопечную ячеку.


Название: Re: Помогите организовать мигание иконки внутри делегата
Отправлено: crossly от Февраль 03, 2010, 20:44
вообще не логично что бы модель управляла миганием... по идее в модели должно быть 2 состояния ... есть аларм или его нету... по этому сувай таймер в делегат...


Название: Re: Помогите организовать мигание иконки внутри делегата
Отправлено: lit-uriy от Февраль 03, 2010, 21:41
2 crossly,
+1


Название: Re: Помогите организовать мигание иконки внутри делегата
Отправлено: neosapient от Февраль 05, 2010, 13:55
Цитировать
вообще не логично что бы модель управляла миганием... по идее в модели должно быть 2 состояния ... есть аларм или его нету... по этому сувай таймер в делегат...
Только тут встает другая проблема - как мне сказать TableView, что таймер требует обновить делегат в такой то ячейке? 
Ведь надо, чтобы делегат знал индекс ячейки для обновления, чтобы он потом от лица модели послал сигнал в слот TableView::update ( const QModelIndex & index ). Делать очень грамоздкую обвеску не хочется... Есть пример с элегантным решением ?


Название: Re: Помогите организовать мигание иконки внутри делегата
Отправлено: crossly от Февраль 07, 2010, 21:19
а зачем тебе говорить об этом tableview .... таймер у тебя будет в делегате... делегат в ячейке... вот и все...


Название: Re: Помогите организовать мигание иконки внутри делегата
Отправлено: Kolobok от Февраль 07, 2010, 22:06
вообще не логично что бы модель управляла миганием... по идее в модели должно быть 2 состояния ... есть аларм или его нету... по этому сувай таймер в делегат...
Еще более нелогично делать таймер в делегате. Я даже больше скажу, это невозможно без очень большой
черезжопности, а может и вообще невозможно. Можно мигание организовать во view, но это довольно сложно.
В модели же это всего несколько строчек.


Название: Re: Помогите организовать мигание иконки внутри делегата
Отправлено: Igors от Февраль 07, 2010, 22:37
Не вдаваясь в конкретные подробности реализации:

1) Расслабиться. Задачка простая - значит и решаться должна просто

2) Таймер завязать на таблицу (а не на ячейку) - это однозначно. А вдруг кто-то еще захочет мигать?

3) Таблица получает сигнал от таймера и передает его выбранной ячейке (может строке/столбцу) - а та уж знает что с ним делать (по умолчанию - ничего), простой virtual, хорошо подходит множественное наследование


Название: Re: Помогите организовать мигание иконки внутри делегата
Отправлено: Kolobok от Февраль 08, 2010, 13:05
Задачка простая - значит и решаться должна просто
Если что-то дешево, значит это плохо? Бывает, простые задачи вообще не имеют решения. Ни простого, ни сложного.

2) Таймер завязать на таблицу (а не на ячейку) - это однозначно. А вдруг кто-то еще захочет мигать?
Так этот вариант вообще еще не обсуждался. Было предложено хранить таймер в модели, вью или делегате. Кстати, это очень неплохой вариант.
В мигающие ячейки сажать виджет и коннектить его с таймером. Подходит для небольших таблиц.

3) Таблица получает сигнал от таймера и передает его выбранной ячейке (может строке/столбцу) - а та уж знает что с ним делать (по умолчанию - ничего), простой virtual, хорошо подходит множественное наследование
Честно говоря, не понимаю что здесь написано.
Что значит выбранная ячейка? Откуда вью знает, какие ячейки должны мигать?
Что значит передать ячейке? Ячейка - это QModelIndex.


Название: Re: Помогите организовать мигание иконки внутри делегата
Отправлено: lit-uriy от Февраль 08, 2010, 13:50
>>Ячейка - это QModelIndex.
Нет. Ячейка в пердставлении - это делегат.
QModelIndex - это координата и только.


Название: Re: Помогите организовать мигание иконки внутри делегата
Отправлено: Kolobok от Февраль 08, 2010, 15:22
>>Ячейка - это QModelIndex.
Нет. Ячейка в пердставлении - это делегат.
QModelIndex - это координата и только.
Неинтуитивное название делегата. Таблица с одной ячейкой звучит более чем странно.


Название: Re: Помогите организовать мигание иконки внутри делегата
Отправлено: Igors от Февраль 08, 2010, 15:35
Что значит выбранная ячейка? Откуда вью знает, какие ячейки должны мигать?
Что значит передать ячейке? Ячейка - это QModelIndex.
Data model всегда есть. Нарастите этот класс чтобы он умел давать разные цвета ячейкам, напр.

Код:
class MyDataModel : public QAbstractItemModel {
....
virtual void data( ..);  // добавить выдачу для Qt::BackgroundRole
...

void NextBlink( void ) { mBlinkState = (mBlinkState + 1) % 2; }

QVector <QModelIndex> mBlinkCell; // массив мигающих ячеек
int mBlinkState:                          // напр. 0 = синий, 1 = красный и.т.п.
};
По таймеру таблица говорит модели NextBlink и вызывает перерисовку нужных ячеек.
Правда, судя по исходникам, background (возвращаемый data) будет игнорироваться для выделенных ячеек если showDecorationSelected = true в стиле. Но оно public, так что можно напр. перекрыть paint для делегата. Короче, раскрасить ячейку можно  :)


Название: Re: Помогите организовать мигание иконки внутри делегата
Отправлено: Kolobok от Февраль 08, 2010, 16:39
Код:
class MyDataModel : public QAbstractItemModel {
....
virtual void data( ..);  // добавить выдачу для Qt::BackgroundRole
...

void NextBlink( void ) { mBlinkState = (mBlinkState + 1) % 2; }

QVector <QModelIndex> mBlinkCell; // массив мигающих ячеек
int mBlinkState:                          // напр. 0 = синий, 1 = красный и.т.п.
};
По таймеру таблица говорит модели NextBlink и вызывает перерисовку нужных ячеек.
Правда, судя по исходникам, background (возвращаемый data) будет игнорироваться для выделенных ячеек если showDecorationSelected = true в стиле. Но оно public, так что можно напр. перекрыть paint для делегата. Короче, раскрасить ячейку можно  :)
В этом варианте мигающие элементы придется хранить и во view(очень плохо). Или по сигналу таймера вызывать repaint().


Название: Re: Помогите организовать мигание иконки внутри делегата
Отправлено: crossly от Февраль 08, 2010, 16:51
а вы не рассматривали вариант засовывания gif-анимации в делегат??


Название: Re: Помогите организовать мигание иконки внутри делегата
Отправлено: Kolobok от Февраль 08, 2010, 17:26
а вы не рассматривали вариант засовывания gif-анимации в делегат??

Не работает. Я думаю gif-анимация работает только в виджетах.


Название: Re: Помогите организовать мигание иконки внутри делегата
Отправлено: crossly от Февраль 08, 2010, 17:45
а как пробовали?? посмотри как реализовано в QLabel


Название: Re: Помогите организовать мигание иконки внутри делегата
Отправлено: Kolobok от Февраль 08, 2010, 18:01
Делегат в принципе не может делать анимацию сам, потому что он не знает ничего ни о модели, ни о вью, ни о том, где во вью расположены элементы.


Название: Re: Помогите организовать мигание иконки внутри делегата
Отправлено: lit-uriy от Февраль 08, 2010, 18:58
делегат можно сделать специализированный, на то его и придумали, иначеб было только представление да модель


Название: Re: Помогите организовать мигание иконки внутри делегата
Отправлено: break от Февраль 08, 2010, 19:09
идея на счет gif анимации и специализированного делегата кажется наиболее здравой, делегат может в своем painEvent проерять условие из вне и решать какой frame из gif рисовать


Название: Re: Помогите организовать мигание иконки внутри делегата
Отправлено: Kolobok от Февраль 08, 2010, 19:17
идея на счет gif анимации и специализированного делегата кажется наиболее здравой, делегат может в своем painEvent проерять условие из вне и решать какой frame из gif рисовать
Делегат не виджет. У него нет paintEvent.


Название: Re: Помогите организовать мигание иконки внутри делегата
Отправлено: break от Февраль 08, 2010, 19:21
Код
C++ (Qt)
class CBtn_Delegate : public QItemDelegate
{
Q_OBJECT;
QString m_sIconPath;
 
public:
CBtn_Delegate( QObject * parent = 0 );
QWidget * createEditor( QWidget * parent,
const QStyleOptionViewItem &option,
const QModelIndex &index ) const;
void setEditorData( QWidget * editor, const QModelIndex &index ) const;
void setModelData( QWidget *editor, QAbstractItemModel *model,
  const QModelIndex &index ) const;
void updateEditorGeometry( QWidget *editor,
  const QStyleOptionViewItem &option,
  const QModelIndex &index) const;
void paint( QPainter * painter, const QStyleOptionViewItem &option,
const QModelIndex &index ) const;
 
inline void setIconPath( QString sVal ) { m_sIconPath = sVal; }
};
 

Код
C++ (Qt)
void CBtn_Delegate::paint( QPainter * painter, const QStyleOptionViewItem &option,
 const QModelIndex &index ) const
{
QWidget * w = dynamic_cast<QWidget *>( painter->device() );
if ( w )
{
QStylePainter p( w );
QStyleOptionButton opt;
opt.icon = QIcon( m_sIconPath );
opt.iconSize = QSize( 24, 24 );
opt.initFrom( w );
opt.rect = option.rect;
 
bool bChecked = index.data().toInt() > 0;
if ( bChecked )
opt.state |= QStyle::State_On;
p.drawControl( QStyle::CE_PushButton, opt );
}
 
drawFocus( painter, option, option.rect );
}
 

народ выходим из танков, сказал по памяти там он называется просто paint - предназначен для отрисовки ячейки когда не создан эдитор. Думаю у делегата мигалки эдитора вообще не должно быть (а может и нет). Кстати как автор хочем чтобы все мигали разом или в такат? :-) Все это легко делается - но мое мнение что отвлекать будет жутко от основных данных в таблице - достаточно просто иконок... IMHO


Название: Re: Помогите организовать мигание иконки внутри делегата
Отправлено: Kolobok от Февраль 08, 2010, 19:38
И где здесь анимация?


Название: Re: Помогите организовать мигание иконки внутри делегата
Отправлено: break от Февраль 08, 2010, 19:40
Ее там нет(я и не утверждал обратное) это просто пример моего делегата кот. первый попался на глаза в проекте, код выложил чтобы не быть голословным на счет pain в делегате.


Название: Re: Помогите организовать мигание иконки внутри делегата
Отправлено: neosapient от Февраль 08, 2010, 20:45
>> Кстати как автор хочем чтобы все мигали разом или в такат?
Автор хочет, чтобы мигало в такт.

Вообще, внимательно слежу за развитием дискуссии... Способ, по которому пошел, я описал выше в 5 посте.

Медленно, но верно прихожу к выводу, что анимацию исключительно на делегат повесить нельзя. Пришел к мысли, что анимация в ячейках таблицы реализуема только в связке delegat+model+timer или в более общем случае delegat+model+event. И способов убрать модель из этой связке нет, по той причине, что следует от имени модели посылать сигнал QAbstractItemModel::dataChanged(QModelIndex,QModelIndex).
В общем делегаты хороши для статической отрисовки. Да и вся QAbstractItem-архитектура заточена для статической отрисовки.

(очень хочется, чтобы я ошибался, но факты упрямая вещь)

Timer->   Model      ->  Table   ->Delegat
Event->dataChange->rendering->paint


Название: Re: Помогите организовать мигание иконки внутри делегата
Отправлено: Kolobok от Февраль 08, 2010, 22:51
А таблица большая? И сколько может быть мигающих элементов?

Захотелось сказать пару слов о самой идее. Мигающую таблицу я стал бы делать только для клиента, которого тихо ненавижу. Существует столько способов выделить нужные строки ( цвет фона или  шрифта, размер шрифта или строки ... ), которые привлекают внимание и не приводят к нервному срыву.

PS
Придумал еще один способ. Повесить прокси модель, которая пропускает максимальное количество видимых строк, на мигающие ячейки повесить виджеты с анимацией и прикрутить сбоку скроллбар.


Название: Re: Помогите организовать мигание иконки внутри делегата
Отправлено: Igors от Февраль 09, 2010, 01:11
Код
C++ (Qt)
void CBtn_Delegate::paint( QPainter * painter, const QStyleOptionViewItem &option,
 const QModelIndex &index ) const
{
QWidget * w = dynamic_cast<QWidget *>( painter->device() );
if ( w )
{
QStylePainter p( w );
QStyleOptionButton opt;
opt.icon = QIcon( m_sIconPath );
 
... Все это легко делается ...
[/quote]Не вызывает сомнений что Вы владеете Qt, и для Вас это действительно легко. Но чего это надо перекрывать paint (т.е. брать на себя рисование) только для того чтобы изменить background? Чем плохо просто дополнить модель? У модели все на руках, все данные она знает, ну и пусть занимается также и цветом фона - зачем это совать в делегат который так себе "прослойка интеллигенция"?  :)


Название: Re: Помогите организовать мигание иконки внутри делегата
Отправлено: break от Февраль 09, 2010, 10:56
Цитировать
Да и вся QAbstractItem-архитектура заточена для статической отрисовки.
Поясните конкретнее что вы имеете ввиду. Что нельзя написать модель так чтобы при частых изменениях в данных эти изменения происходили во VIEW? если я правильно понял то вы ошибаетесь это вполне можно сделать.

Цитировать
Но чего это надо перекрывать paint (т.е. брать на себя рисование) только для того чтобы изменить background? Чем плохо просто дополнить модель? У модели все на руках, все данные она знает, ну и пусть занимается также и цветом фона - зачем это совать в делегат который так себе "прослойка интеллигенция"?
Для меня модель это данные - а в данных просто где-то стоит галочка что эта строка/ячейка/столбец особенные. И вот однажды эту особенность захотелось выделить в таблице миганием - при чем тут модель? А завтра в другой таблице этого не захочется - а в модели останется ненужный функционал, которые вообще ничего не делает с данными а как раз занимается декорациями. Мне кажется здесь как раз вполне нормально использовать делегат для реализации таких декораций. Тем более что с производительностью проблем быть не должно, делегаты для того и придуманы чтобы установить его на колонку и не забивать голову про производительность (при такой установке создается 1 экземпляр класса делегата код которого вызывается при отрисовке каждой ячейки вместо стандартного кода отрисовки ячеек).

По поводу связки с таймером - тоже не вижу особых проблем - даже несколько способов можно придумать:
1) Делегат имеет право иметь слот который будет сконнекчен с сигналом таймера (QTimer) заведенным в программе (ни в моделе, ни в таблице - просто в окне в котором моздается эта таблица будет еще и таймер),
2) Можно не использовать QTimer и сигналы со слотами - а стартовать таймер через int QObject::startTimer ( int interval ) в делегат передать ID созданного таймера и там слушать его в  void MyObject::timerEvent(QTimerEvent *event) проверяя на совпадение с заданным ID

по сигналу от таймера в делегате переключается отрисовываемый фрейм или грубо говоря выбираем картинку одну из двух для отрисовки в данный момент.


Название: Re: Помогите организовать мигание иконки внутри делегата
Отправлено: Kolobok от Февраль 09, 2010, 12:12
to break
Я не просто так говорил, что делегат не виджет и у него нет paintEvent. Почитай документацию о том, как происходит рисование в Qt.


Название: Re: Помогите организовать мигание иконки внутри делегата
Отправлено: break от Февраль 09, 2010, 12:27
Цитировать
Я не просто так говорил, что делегат не виджет и у него нет paintEvent. Почитай документацию о том, как происходит рисование в Qt.
В чем проблема?


Название: Re: Помогите организовать мигание иконки внутри делегата
Отправлено: lit-uriy от Февраль 09, 2010, 12:38
Kolobok и break
каждый из вас по своему прав, но каждый из вас до конца не рассказывает оппоненту свою мысль.

у делегата действительно нет функции  paintEvent. У него есть функция paint.
В событии рисования представления, т.е. в его paintEvent по мимо рисования того, что непосредственно к нему относится, ещё вызываются функции paint всех делегатов, которые видны в данный момент и все предшествующие им.
Т.е. если в данный момент в таблице видны строки/столбцы в диаппазоне 5...9, то вызываются методы рисования делегатов принадлежащих строкам/столбцам с 0 по 9.

Итого: инициатором рисования делегата является представление, но весь алгоритм рисования делегата находится в самом делегате


Название: Re: Помогите организовать мигание иконки внутри делегата
Отправлено: BRE от Февраль 09, 2010, 12:50
Набросал примерчик. С картинками затеваться было лениво, сделал мигание слова 'Alarm', если в ячейке находиться буква 'A'
Для оптимизации желательно добавить обновление не всего viewport, а только области для нужной колонки, тоже стало лениво :)
Хотя, Qt сам частенько обнавляет весь viewport...
Код
C++ (Qt)
#include <QApplication>
#include <QTableView>
#include <QItemDelegate>
#include <QStandardItemModel>
#include <QPainter>
#include <QTimer>
#include <QDebug>
 
class Delegate : public QItemDelegate
{
       Q_OBJECT
public:
       Delegate() : m_state( false ) {}
 
       void paint( QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index ) const;
 
public slots:
       void stateChanged()
       {
               m_state = !m_state;
       }
 
private:
       bool    m_state;
};
 
void Delegate::paint( QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index ) const
{
       if( !index.isValid() )
               return;
 
       painter->save();
       QString val = index.data( Qt::DisplayRole ).toString();
       if( val == "A" )
               painter->drawText( option.rect, m_state? "Alarm" : "" );
       else
               painter->drawText( option.rect, val );
       painter->restore();
}
 
int main( int argc, char *argv[] )
{
       QApplication app( argc, argv );
 
       QStandardItemModel model( 10, 10 );
       model.setItem( 1, 0, new QStandardItem( "A" ) );
       model.setItem( 3, 0, new QStandardItem( "A" ) );
       model.setItem( 4, 0, new QStandardItem( "A" ) );
       Delegate delegate;
 
       QTableView view;
       view.setModel( &model );
       view.setItemDelegateForColumn( 0, &delegate );
       view.show();
 
 
       // Таймер меняет состояние и заставляет перерисоваться view
       QTimer timer;
       QObject::connect( &timer, SIGNAL( timeout() ), &delegate, SLOT( stateChanged() ) );
       QObject::connect( &timer, SIGNAL( timeout() ), view.viewport(), SLOT( update() ) );
       timer.start( 1000 );
 
       return app.exec();
}
 
#include "main.moc"
 


Название: Re: Помогите организовать мигание иконки внутри делегата
Отправлено: Kolobok от Февраль 09, 2010, 12:51
Я извиняюсь за лаконичность. Клавиатура виртуальная. :(

Рисовать делегат может только внутри paintEvent представления. Поэтому вызывать таймером какие-либо слоты делегата для перерисовки смысла не имеют.


Название: Re: Помогите организовать мигание иконки внутри делегата
Отправлено: crossly от Февраль 09, 2010, 12:54
Я извиняюсь за лаконичность. Клавиатура виртуальная. :(

Рисовать делегат может только внутри paintEvent представления. Поэтому вызывать таймером какие-либо слоты делегата для перерисовки смысла не имеют.
простите .... где вы говорите это написано.... ??


Название: Re: Помогите организовать мигание иконки внутри делегата
Отправлено: BRE от Февраль 09, 2010, 12:57
Рисовать делегат может только внутри paintEvent представления. Поэтому вызывать таймером какие-либо слоты делегата для перерисовки смысла не имеют.
Ну так оттуда и зовется QAbstractItemDelegate::paint.


Название: Re: Помогите организовать мигание иконки внутри делегата
Отправлено: Kolobok от Февраль 09, 2010, 13:02
простите .... где вы говорите это написано.... ??
Где написано что?


Название: Re: Помогите организовать мигание иконки внутри делегата
Отправлено: crossly от Февраль 09, 2010, 13:34
Цитировать
вызывать таймером какие-либо слоты делегата для перерисовки смысла не имеют.


Название: Re: Помогите организовать мигание иконки внутри делегата
Отправлено: Kolobok от Февраль 09, 2010, 13:45
Потому что у делегата нет QPaintDevice. Ему не на чем рисовать. Кроме того, он не знает, что рисовать и где. Все это делегат может получить только из paintEvent представления, но никак от таймера.


Название: Re: Помогите организовать мигание иконки внутри делегата
Отправлено: crossly от Февраль 09, 2010, 13:47
тем не менее приведенный выше пример работает....


Название: Re: Помогите организовать мигание иконки внутри делегата
Отправлено: Kolobok от Февраль 09, 2010, 13:59
тем не менее приведенный выше пример работает....
Потому что представление каждую секунду принудительно перерисовывается. Этот способ я уже описывал.
Код:
class MyDataModel : public QAbstractItemModel {
....
virtual void data( ..);  // добавить выдачу для Qt::BackgroundRole
...

void NextBlink( void ) { mBlinkState = (mBlinkState + 1) % 2; }

QVector <QModelIndex> mBlinkCell; // массив мигающих ячеек
int mBlinkState:                          // напр. 0 = синий, 1 = красный и.т.п.
};
По таймеру таблица говорит модели NextBlink и вызывает перерисовку нужных ячеек.
Правда, судя по исходникам, background (возвращаемый data) будет игнорироваться для выделенных ячеек если showDecorationSelected = true в стиле. Но оно public, так что можно напр. перекрыть paint для делегата. Короче, раскрасить ячейку можно  :)
В этом варианте мигающие элементы придется хранить и во view(очень плохо). Или по сигналу таймера вызывать repaint().


Название: Re: Помогите организовать мигание иконки внутри делегата
Отправлено: break от Февраль 09, 2010, 14:15
Цитировать
Потому что у делегата нет QPaintDevice. Ему не на чем рисовать. Кроме того, он не знает, что рисовать и где. Все это делегат может получить только из paintEvent представления, но никак от таймера.
Что рисовать делегат знает по тз., где рисовать тоже знает - это передается входными параметрами в ф-ю paint.
Таймер предлагался к использованию для изменения флажка состояния. Как и приведено в примере выше у BRE.
Да и в принцепе для мигания - вам один хрен будет нужен таймер, а иначе как???
Совершенно непонятно чем не нравится приведенный пример. Хранить функционал мигания в моделе уж точно худшая мысль. Писать вьюв который будет уметь мигать - тоже бред, чтобы этого не делать и были придуманы делегаты.
IMHO: Ерундовая тема раздулась на 3 страницы - совершенно непонятно почему и зачем.


Название: Re: Помогите организовать мигание иконки внутри делегата
Отправлено: crossly от Февраль 09, 2010, 14:17
совершенно согласен....


Название: Re: Помогите организовать мигание иконки внутри делегата
Отправлено: Kolobok от Февраль 09, 2010, 15:09
Хранить флаг анимации и управлять анимацией это разные вещи. Первое может быть в модели или делегате, второе в модели или вью. Где - не принципиально если не требуется оптимизация. Все это время я пытался сказать, что делегат не может управлять анимацией.

ИМХО лучше весь код иметь в одном классе.


Название: Re: Помогите организовать мигание иконки внутри делегата
Отправлено: crossly от Февраль 09, 2010, 15:17
тем не менее приведенный здесь код говорит об обратном... :)


Название: Re: Помогите организовать мигание иконки внутри делегата
Отправлено: BRE от Февраль 09, 2010, 16:09
Хранить флаг анимации и управлять анимацией это разные вещи. Первое может быть в модели или делегате, второе в модели или вью. Где - не принципиально если не требуется оптимизация.
Что значит не принципиально?
Есть одна модель, которая представляет данные для нескольких вьюшек.
Для каждой вьюшки состояние аварии показывается по разному. Для одной (это таблица) - миганием иконки в ячейке, для другой (а это может быть и какой нибудь QGraphicsView) - разбегающимися слониками. Для поддержки второго типа индикации, тоже добавим еще один специальный столбик в модель, для сохранения координат слоников?  :)
Модель - предоставила данные - АВАРИЯ, как и кто это будет сигнализировать для нее вопрос не интересный.

ИМХО лучше весь код иметь в одном классе.
А это все можно скрыть внутри, С++ же.  :)


Название: Re: Помогите организовать мигание иконки внутри делегата
Отправлено: break от Февраль 09, 2010, 16:44
Цитировать
Модель - предоставила данные - АВАРИЯ, как и кто это будет сигнализировать для нее вопрос не интересный.
тоже согласен

Цитировать
лучше весь код иметь в одном классе
не всегда так - пример со слониками выше (не подумайте что он надуман - очень даже актуальный) - как раз доказывает обратное, иногда желание хранить все в 1 месте пораждает перегруженные классы с которыми не понятно как и неудобно работать


Название: Re: Помогите организовать мигание иконки внутри делегата
Отправлено: Kolobok от Февраль 09, 2010, 17:25
Кстати о слониках. Представте себе делегата с тяжелым методом paint. Представление будет себя постоянно перерисовывать и на остальное ресурсов может не хватить.


Название: Re: Помогите организовать мигание иконки внутри делегата
Отправлено: Igors от Февраль 09, 2010, 17:43
Потому что представление каждую секунду принудительно перерисовывается. Этот способ я уже описывал.
В этом варианте мигающие элементы придется хранить и во view(очень плохо). Или по сигналу таймера вызывать repaint().
Как же Вы собираетесь организовать мигание без принудительной перерисовки с интервалом мигания ? :)
И зачем хранить "и во view(очень плохо)"? Чем так уж плохо хранить в модели? Ладно, почему-то не хотите, так есть масса разумных вариантов, напр.

- мне здесь нравится множественное наследование
Код:
class MyDataModel : public QAbstractItemModel, public Blinker {
И если надо через dynamic_cast узнаем, может ли таблица мигать.

- также сделать Blinker отдельным классом и модель имеет указатель на него (членство вместо наследования)

- ладно, если уж хочется "общности/универсальности" - делаем вызов какого-то virtual'a в методе модели data()   
и.т.д.  и.т.п.

А вообще "проблема мигания" на мой взгляд не заслуживает обсуждения, сигнал таймера можно получить где угодно. Реально-то обсуждается "как покрасить ячейку" - и здесь ходов раз-два и обчелся. Перекрыть paint (полностью) конечно можно, но это "brute force". Так что ото приспосабливайте модель - и дело с концом.


Название: Re: Помогите организовать мигание иконки внутри делегата
Отправлено: Kolobok от Февраль 09, 2010, 17:57
Как же Вы собираетесь организовать мигание без принудительной перерисовки с интервалом мигания ? :)
Без принудительной перерисовки - никак. Но модель может заставить представление перерисовывать только мигающие ячейки.

Чем так уж плохо хранить в модели?
Разве я говорил обратное.


Название: Re: Помогите организовать мигание иконки внутри делегата
Отправлено: crossly от Февраль 09, 2010, 18:07
а давайте спросим у Тролей.... что они по этому поводу думают... :)


Название: Re: Помогите организовать мигание иконки внутри делегата
Отправлено: lit-uriy от Февраль 09, 2010, 18:45
Цитировать
Представте себе делегата с тяжелым методом paint. Представление будет себя постоянно перерисовывать и на остальное ресурсов может не хватить.
А если не делегат то ресурсы откуда-то появятся на рисоваиние?
Цитировать
ИМХО лучше весь код иметь в одном классе.
это устаревший подход под названием "мухи вместе с катлетами". Его подобие реализовано в QTableWidget.


Название: Re: Помогите организовать мигание иконки внутри делегата
Отправлено: break от Февраль 09, 2010, 18:57
Цитировать
Без принудительной перерисовки - никак. Но модель может заставить представление перерисовывать только мигающие ячейки.
Охренеть а делегат что будет перерисовывать в том числе и невидимые немигающие???
Цитировать
Кстати о слониках. Представте себе делегата с тяжелым методом paint. Представление будет себя постоянно перерисовывать и на остальное ресурсов может не хватить.
Ну да метод paint сильно потяжелел из-за отрисовки 2-х картинок по очереди... А если в модели хранить кучу флажков для каждого варианта представления - то ни у кого не хватит желания потом в этой модели разбираться.

Зачем тогда вообще использовать схему модель-представление - если у вас декорации с данными путаются?

Множественное наследование - это зло, а уж множественное наследование для реализации мигания - еще большее зло. В идеале множественное наследование вообще только от интерфейсных (абстрактных) классов должно быть.

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


Название: Re: Помогите организовать мигание иконки внутри делегата
Отправлено: lit-uriy от Февраль 09, 2010, 19:02
>>но мне не нравится идея хранить в модели признак мигания
Признак мигания только там и хранить (точнее от туда брать), но признак это всего лишь информация о том, что "нужно мигать", а не о том, "как мигать".
Флажок состояния (светится/потушен) это не признак мигания, а внутренняя реализация конечного автомата.


Название: Re: Помогите организовать мигание иконки внутри делегата
Отправлено: Kolobok от Февраль 09, 2010, 19:20
А если не делегат то ресурсы откуда-то появятся на рисоваиние?
модель может заставить представление перерисовывать только мигающие ячейки.

это устаревший подход под названием "мухи вместе с катлетами". Его подобие реализовано в QTableWidget.
Когда QTableWidget стал устаревшим?

Цитировать
Без принудительной перерисовки - никак. Но модель может заставить представление перерисовывать только мигающие ячейки.
Охренеть а делегат что будет перерисовывать в том числе и невидимые немигающие???
???

Ну да метод paint сильно потяжелел из-за отрисовки 2-х картинок по очереди...
В модели могут быть данные, которые генерируются "на лету". Про мигающий столбик вообще речи не было. Его то по-любому перерисовывать надо.


Название: Re: Помогите организовать мигание иконки внутри делегата
Отправлено: lit-uriy от Февраль 09, 2010, 20:04
>>модель может заставить представление перерисовывать только мигающие ячейки.
Заставить не может, нет у неё такой власти.  Модель сообщает диапазон изменений, но это поведение по умолчанию.

>>Когда QTableWidget стал устаревшим?
Не виджет устаревший, а подход. Читай доку по нему там явно об этом говорится.



Название: Re: Помогите организовать мигание иконки внутри делегата
Отправлено: Igors от Февраль 09, 2010, 20:45
Пацаны, мне кажется "слишком много теоретизируем"  :) Более практично склепать вариант (их уже предложено не один) а потом "по жизни" смотреть где и что жмет, что плохо. Если этот класс постоянно/навязчиво требует внимания - надо перепланировать (ничего смертельного здесь нет). А если делает все что надо - так нечего время терять, др. работы полно


Название: Re: Помогите организовать мигание иконки внутри делегата
Отправлено: break от Февраль 09, 2010, 20:49
+1