Russian Qt Forum
Май 21, 2024, 01:37 *
Добро пожаловать, Гость. Пожалуйста, войдите или зарегистрируйтесь.
Вам не пришло письмо с кодом активации?

Войти
 
  Начало   Форум  WIKI (Вики)FAQ Помощь Поиск Войти Регистрация  

Страниц: 1 2 [3] 4   Вниз
  Печать  
Автор Тема: Помогите организовать мигание иконки внутри делегата  (Прочитано 33002 раз)
lit-uriy
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 3880


Просмотр профиля WWW
« Ответ #30 : Февраль 09, 2010, 12:38 »

Kolobok и break
каждый из вас по своему прав, но каждый из вас до конца не рассказывает оппоненту свою мысль.

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

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

Юра.
BRE
Гость
« Ответ #31 : Февраль 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"
 
« Последнее редактирование: Февраль 09, 2010, 12:55 от BRE » Записан
Kolobok
Гость
« Ответ #32 : Февраль 09, 2010, 12:51 »

Я извиняюсь за лаконичность. Клавиатура виртуальная. Грустный

Рисовать делегат может только внутри paintEvent представления. Поэтому вызывать таймером какие-либо слоты делегата для перерисовки смысла не имеют.
Записан
crossly
Гость
« Ответ #33 : Февраль 09, 2010, 12:54 »

Я извиняюсь за лаконичность. Клавиатура виртуальная. Грустный

Рисовать делегат может только внутри paintEvent представления. Поэтому вызывать таймером какие-либо слоты делегата для перерисовки смысла не имеют.
простите .... где вы говорите это написано.... ??
Записан
BRE
Гость
« Ответ #34 : Февраль 09, 2010, 12:57 »

Рисовать делегат может только внутри paintEvent представления. Поэтому вызывать таймером какие-либо слоты делегата для перерисовки смысла не имеют.
Ну так оттуда и зовется QAbstractItemDelegate::paint.
Записан
Kolobok
Гость
« Ответ #35 : Февраль 09, 2010, 13:02 »

простите .... где вы говорите это написано.... ??
Где написано что?
Записан
crossly
Гость
« Ответ #36 : Февраль 09, 2010, 13:34 »

Цитировать
вызывать таймером какие-либо слоты делегата для перерисовки смысла не имеют.
Записан
Kolobok
Гость
« Ответ #37 : Февраль 09, 2010, 13:45 »

Потому что у делегата нет QPaintDevice. Ему не на чем рисовать. Кроме того, он не знает, что рисовать и где. Все это делегат может получить только из paintEvent представления, но никак от таймера.
Записан
crossly
Гость
« Ответ #38 : Февраль 09, 2010, 13:47 »

тем не менее приведенный выше пример работает....
Записан
Kolobok
Гость
« Ответ #39 : Февраль 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().
Записан
break
Гипер активный житель
*****
Offline Offline

Сообщений: 846


Просмотр профиля
« Ответ #40 : Февраль 09, 2010, 14:15 »

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

совершенно согласен....
Записан
Kolobok
Гость
« Ответ #42 : Февраль 09, 2010, 15:09 »

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

ИМХО лучше весь код иметь в одном классе.
Записан
crossly
Гость
« Ответ #43 : Февраль 09, 2010, 15:17 »

тем не менее приведенный здесь код говорит об обратном... Улыбающийся
Записан
BRE
Гость
« Ответ #44 : Февраль 09, 2010, 16:09 »

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

ИМХО лучше весь код иметь в одном классе.
А это все можно скрыть внутри, С++ же.  Улыбающийся
Записан
Страниц: 1 2 [3] 4   Вверх
  Печать  
 
Перейти в:  


Страница сгенерирована за 0.124 секунд. Запросов: 23.