Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Мерцание StringGrid при определении OnDrawCell 
V
    Опции темы
Нитонисе
Дата 11.10.2013, 16:33 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 917
Регистрация: 5.11.2009

Репутация: 2
Всего: 2



Если определить обработчик OnDrawCell, то при перерисовке грида происходит заметное мерцание. Например я просто щелкаю мышкой по разным ячейкам и после каждого щелчка видно как грид перерисовывается. Если же этот обработчик не определять, то такое мерцание если и имеет место быть, то в гораздо меньшей степени. С чем это связано? Такое ощущение, что если не определить OnDrawCell, то грид не полностью перерисовывается при том же кликании по ячейкам мышью, а рисуются заново лишь те ячейки, по которым кликаю.
PM MAIL   Вверх
sawfish
Дата 11.10.2013, 19:40 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


Профиль
Группа: Участник
Сообщений: 150
Регистрация: 30.7.2008
Где: Новосибирск

Репутация: 8
Всего: 8



Если при не определении обработчика OnDrawCell мерцание всё равно остается, то дело не в OnDrawCell.
Проверьте, нет ли где-нибудь лишних Repaint или Refresh.
PM MAIL   Вверх
Нитонисе
Дата 11.10.2013, 21:10 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 917
Регистрация: 5.11.2009

Репутация: 2
Всего: 2



Цитата(sawfish @  11.10.2013,  19:40 Найти цитируемый пост)
Если при не определении обработчика OnDrawCell мерцание всё равно остается, то дело не в OnDrawCell.
Проверьте, нет ли где-нибудь лишних Repaint или Refresh. 

Да, вы правы. Дело не в OnDrawCell. Есть еще обработчик OnMouseDown, где я применяю метод Refresh для грида. Но я не знаю как мне без этого обойтись. Я в OnDrawCell отрисовываю ячейки грида выделяя отдельными цветами активную строку и активную ячейку. Если не применять метод Refresh при клике мышкой по ячейке - не получается нужная мне закраска активной строки. Прикладываю поясняющую картинку. Можно ли добиться эффекта как на первой картинке без метода Refresh в обработчике OnMouseDown (имеется ввиду при клике мышкой по ячейкам грида)?

user posted image
PM MAIL   Вверх
sawfish
Дата 14.10.2013, 08:24 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


Профиль
Группа: Участник
Сообщений: 150
Регистрация: 30.7.2008
Где: Новосибирск

Репутация: 8
Всего: 8



Я вообще обработчик OnMouseDown не трогаю, всё должно прекрасно отрисовываться без него   smile 
Repaint у StringGrid'а в моей проге вызывается только в трех случаях:
- при изменении размеров окна
- при условии отображения выделения цветом (моя настройка в проге)
- в обработчике OnTopLeftChanged (у меня там строки разной высоты + объединение ячеек)
PM MAIL   Вверх
sawfish
Дата 16.10.2013, 11:47 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


Профиль
Группа: Участник
Сообщений: 150
Регистрация: 30.7.2008
Где: Новосибирск

Репутация: 8
Всего: 8



Нитонисе, справились с мерцанием?
PM MAIL   Вверх
Нитонисе
Дата 16.10.2013, 21:19 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 917
Регистрация: 5.11.2009

Репутация: 2
Всего: 2



Цитата(sawfish @  16.10.2013,  11:47 Найти цитируемый пост)
Нитонисе, справились с мерцанием? 

Да. Сделал новый класс, наследник от StringGrid, в котором открыл функцию родительского класса InvalidateRow. Она перерисовывает строку грида. Перерисовку выполняю на OnSelectCell - перерисовываются строка, в которой выбрана ячейка и та строка, которая была выбрана до этого. Это позволило убрать в обработчиках метод стринггрида Refresh, который перерисовывал грид полностью. Но эти манипуляции мерцание до конца не прибыли. Последний удар был нанесен выставлением свойства DoubleBuffered в true. В коде SGLoads - это компонент класса TAdvStringGrid.

Код

class THackGrid : public TAdvStringGrid
{
    public:
        int PrevRow;
        using TAdvStringGrid::InvalidateRow;
};

__fastcall TFMain::TFMain(TComponent* Owner) : TForm(Owner)
{
    static_cast<THackGrid*>(SGLoads)->PrevRow = SGLoads->Row;
}

void __fastcall TFMain::FormDestroy(TObject *Sender)
{
    static_cast<THackGrid*>(SGLoads)->PrevRow = 0;
}

void __fastcall TFMain::SGLoadsSelectCell(TObject *Sender, int ACol, int ARow, bool &CanSelect)
{
    THackGrid *grid = (THackGrid*)Sender;
    if (grid->PrevRow != ARow)
    {
        grid->InvalidateRow(grid->PrevRow);
        grid->InvalidateRow(ARow);
        grid->PrevRow = ARow;
    }
}


Это сообщение отредактировал(а) Нитонисе - 16.10.2013, 21:20
PM MAIL   Вверх
sawfish
Дата 17.10.2013, 07:51 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


Профиль
Группа: Участник
Сообщений: 150
Регистрация: 30.7.2008
Где: Новосибирск

Репутация: 8
Всего: 8



Жесть! А что так сложно-то? Не, правда, я не понимаю, из-за чего у вас там такие сложности...

Вот мой тестовый пример. На форме StringGrid, CheckBox и RadioGroup.

Код

void __fastcall TForm1::FormCreate(TObject *Sender)
{
    for (int i = 0; i < 5; i++)
    {    for (int j = 0; j < 5; j++)
        {    mySG->Cells[i][j]=String(i+1)+String(j+1);
        }
    }
}
//---------------------------------------------------------------------------
void __fastcall TForm1::mySGDrawCell(TObject *Sender, int ACol, int ARow, TRect &Rect,
          TGridDrawState State)
{
    String sText=((TStringGrid*)Sender)->Cells[ACol][ARow];                     // текст ячейки
    TCanvas* sndCanvas=((TStringGrid*)Sender)->Canvas;                          // канва
    sndCanvas->Font->Color=clWindowText;                                        // цвет шрифта
    if (State.Contains(gdFixed))
        sndCanvas->Brush->Color=clBtnFace;                                      // цвет фиксированной ячейки
    else if (State.Contains(gdSelected) & CBSelected->Checked)
    {   sndCanvas->Brush->Color=clHighlight;                                    // цвет выделенной ячейки
        sndCanvas->Font->Color=clHighlightText;                                 // цвет шрифта
    }
    else
        sndCanvas->Brush->Color=clWhite;                                        // цвет ячейки
    unsigned int uFlag;                                                         // флаг выравнивания
    if (ACol<2 & ARow>0)
        uFlag=DT_LEFT | DT_WORDBREAK;                                           // по левому краю
    else
        uFlag=DT_CENTER | DT_WORDBREAK;                                         // по центру
    sndCanvas->FillRect(Rect);                                               // очистка ячейки
    Rect.Top+=2;
    Rect.Left+=2;
    Rect.Right-=2;
    Rect.Bottom-=2;
    DrawText(sndCanvas->Handle, sText.c_str(), -1, &Rect, uFlag);            // отрисовка
}
//---------------------------------------------------------------------------
void __fastcall TForm1::CBSelectedClick(TObject *Sender)
{
    mySG->Repaint();
}
//---------------------------------------------------------------------------

void __fastcall TForm1::RGSelectClick(TObject *Sender)
{
    if (RGSelect->ItemIndex)
        mySG->Options<<(TGridOption)goRowSelect;
    else
        mySG->Options>>(TGridOption)goRowSelect;
}
//---------------------------------------------------------------------------


Ничего не мерцает.

user posted image

Это сообщение отредактировал(а) sawfish - 17.10.2013, 07:53
PM MAIL   Вверх
Нитонисе
Дата 18.10.2013, 22:52 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 917
Регистрация: 5.11.2009

Репутация: 2
Всего: 2



Цитата(sawfish @  17.10.2013,  07:51 Найти цитируемый пост)
Жесть! А что так сложно-то? Не, правда, я не понимаю, из-за чего у вас там такие сложности...

Ну, во-первых у вас пример немного неправильный. У меня при выделении строки непосредственно выделенная ячейка закрашивается темным цветом, а все остальные ячейки этой же строки - светлоголубым. Как на моих скриншотах выше. При этом свойство goRowSelect = false. При этом, нужно чтобы отрисовка корректно работала при любых способах навигации по гриду (мышью или с клавиатуры). 
Ну и во-вторых - я использую не родной грид, а из набора компонентов TMS. Там этот грид называется TAdvStringGrid.
PM MAIL   Вверх
sawfish
Дата 20.10.2013, 17:16 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


Профиль
Группа: Участник
Сообщений: 150
Регистрация: 30.7.2008
Где: Новосибирск

Репутация: 8
Всего: 8



Цитата

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

 smile 
А что мешает сделать проверку и подставить нужный цвет ячейки в нужной строке в моем примере? 

Цитата

При этом свойство goRowSelect = false.

Эмм... ну у меня тоже какбэ, просто можно менять в ходе отображения.

Цитата

При этом, нужно чтобы отрисовка корректно работала при любых способах навигации по гриду (мышью или с клавиатуры). 


Прекрасно работает!

Цитата

Ну и во-вторых - я использую не родной грид, а из набора компонентов TMS.

С этого нужно было начинать свой первый пост.
PM MAIL   Вверх
Нитонисе
Дата 20.10.2013, 18:44 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 917
Регистрация: 5.11.2009

Репутация: 2
Всего: 2



Цитата(sawfish @  20.10.2013,  17:16 Найти цитируемый пост)
А что мешает сделать проверку и подставить нужный цвет ячейки в нужной строке в моем примере? 

Так у вас такого функционала в принципе нет smile Подставлять некуда.


Цитата(sawfish @  20.10.2013,  17:16 Найти цитируемый пост)
Эмм... ну у меня тоже какбэ, просто можно менять в ходе отображения.

И что? Ну поставили в false - и картина выглядит совсем не так как надо.

Цитата(sawfish @  20.10.2013,  17:16 Найти цитируемый пост)
Прекрасно работает!

Не будет работать, если вы выполните все условия.
PM MAIL   Вверх
sawfish
Дата 21.10.2013, 10:35 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


Профиль
Группа: Участник
Сообщений: 150
Регистрация: 30.7.2008
Где: Новосибирск

Репутация: 8
Всего: 8



(Лирическое отступление. На моем рабочем мониторе не видны светло-голубые ячейки строки на картинке...)

Итак, на форме TStringGrid, и заведена переменная iRow для запоминания индекса строки, на которой выделена ячейка.
goRowSelect = false
goRangeSelect = false

Код

int iRow=1;  // индекс строки, на кот. есть выделенная клетка
//---------------------------------------------------------------------------
void __fastcall TForm1::FormCreate(TObject *Sender)
{
    for (int i = 0; i < 5; i++)
    {    for (int j = 0; j < 5; j++)
        {    mySG->Cells[i][j]=String(i+1)+String(j+1);
        }
    }
}
//---------------------------------------------------------------------------
void __fastcall TForm1::mySGSelectCell(TObject *Sender, int ACol, int ARow, bool &CanSelect)
{
    iRow=ARow;
    mySG->Repaint();
}
//---------------------------------------------------------------------------
void __fastcall TForm1::mySGDrawCell(TObject *Sender, int ACol, int ARow, TRect &Rect,
          TGridDrawState State)
{
    String sText=((TStringGrid*)Sender)->Cells[ACol][ARow];                     // текст ячейки
    TCanvas* sndCanvas=((TStringGrid*)Sender)->Canvas;                          // канва
    sndCanvas->Font->Color=clWindowText;                                        // цвет шрифта
    if (State.Contains(gdFixed))
        sndCanvas->Brush->Color=clBtnFace;                                      // цвет фиксированной ячейки
    else if (State.Contains(gdSelected))
    {   sndCanvas->Brush->Color=clHighlight;                                    // цвет выделенной ячейки
        sndCanvas->Font->Color=clHighlightText;                                 // цвет шрифта
    }
    else if (ARow==iRow)
    {    sndCanvas->Brush->Color=clYellow;  // здесь подставить светло-голубой
    }
    else
        sndCanvas->Brush->Color=clWhite;                                        // цвет ячейки
    unsigned int uFlag;                                                         // флаг выравнивания
    uFlag=DT_CENTER | DT_WORDBREAK;                                          // по центру
    sndCanvas->FillRect(Rect);                                               // очистка ячейки
    Rect.Top+=2;
    Rect.Left+=2;
    Rect.Right-=2;
    Rect.Bottom-=2;
    DrawText(sndCanvas->Handle, sText.c_str(), -1, &Rect, uFlag);            // отрисовка
}



user posted image

Мерцания нет, хоть с DoubleBuffered = true, хоть DoubleBuffered = false.

Цитата

Не будет работать, если вы выполните все условия.


Не знаю, все ли ваши условия выполнены, но прекрасно работает и при навигации клавиатурой!

На TAdvStringGrid не тестировалось.


Это сообщение отредактировал(а) sawfish - 21.10.2013, 10:36
PM MAIL   Вверх
Нитонисе
Дата 21.10.2013, 11:26 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 917
Регистрация: 5.11.2009

Репутация: 2
Всего: 2



Цитата(sawfish @  21.10.2013,  10:35 Найти цитируемый пост)
Лирическое отступление. На моем рабочем мониторе не видны светло-голубые ячейки строки на картинке...

Дело ведь не в конкретном цвете, а в принципе. Закрашиваем своими цветами активную строку и активную ячейку. В вашем примере принцип реализован, но заметно отчетливое мерцание. В этом повинен метод Repaint. Если выставить DoubleBuffered = true - мерцания пропадает. В принципе и у меня можно было бы использовать связку метода Repaint и свойства DoubleBuffered и обойтись без создания класса THackGrid. На малых сетках разницы подозреваю не будет вообще. Но все ж THackGrid с его функцией перерисовки только двух строк, вместо всей сетки - более экономичен. И чем больше по размерам сетка - тем больше этот эффект экономности smile
PM MAIL   Вверх
sawfish
Дата 21.10.2013, 16:56 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


Профиль
Группа: Участник
Сообщений: 150
Регистрация: 30.7.2008
Где: Новосибирск

Репутация: 8
Всего: 8



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

Например, можно было бы всего лишь  закрашивать четные и нечетные строки разными цветами, а выделенная ячейка оставалась бы выделенной (без привязки к строке), и лишних Repaint'ов не было бы:

user posted image

ИМХО

Это сообщение отредактировал(а) sawfish - 21.10.2013, 16:59
PM MAIL   Вверх
Нитонисе
Дата 24.10.2013, 12:12 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 917
Регистрация: 5.11.2009

Репутация: 2
Всего: 2



Цитата(sawfish @  21.10.2013,  16:56 Найти цитируемый пост)
Не люблю создавать и переопределять классы там, где это делается для чего-то малого и несущественного. Если это малое и несущественное создает трудности (условно), несоизмеримые с его реализацией, это отбрасывается или пересматривается.

Да особой пользы от моего класса и нету. Весь смысл от него - использовать метод InvalidateRow, который перерисовывает ряд. Но даже с таким подходом сетка мерцает и я все равно выставил DoubleBuffered = true. И в таком случае можно обойтись без этого нового класса и не пользоваться InvalidateRow, а использовать стандартный Repaint - сетка все равно мерцать не будет, так как DoubleBuffered = true. Я просто оставил этот класс потому что он появился хронологически раньше идеи установки DoubleBuffered = true и я просто не стал его уже удалять smile Работает и работает. Небольшое усложнение, зато все ж более экономичная отрисовка грида smile

А ваша идея с разноцветными строчками - мне такой дизайнерский подход не очень нравится smile
PM MAIL   Вверх
  
Ответ в темуСоздание новой темы Создание опроса
Правила форума "С++ Builder"
Rrader

Запрещается!

1. Публиковать ссылки на вскрытые компоненты

2. Обсуждать взлом компонентов и делиться вскрытыми компонентами

  • Литературу по С++ Builder обсуждаем здесь
  • Действия модераторов можно обсудить здесь
  • С просьбами о написании курсовой, реферата и т.п. обращаться сюда
  • Настоятельно рекомендуем заглянуть в DRKB (Delphi Russian Knowledge Base) - крупнейший в рунете сборник материалов по Дельфи


Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, Rrader.

 
1 Пользователей читают эту тему (1 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | C++ Builder | Следующая тема »


 




[ Время генерации скрипта: 0.0923 ]   [ Использовано запросов: 22 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.