Форум программистов
 

Восстановите пароль или Зарегистрируйтесь на форуме, о проблемах и с заказом рекламы пишите сюда - alarforum@yandex.ru, проверяйте папку спам!

Вернуться   Форум программистов > Delphi программирование > Общие вопросы Delphi
Регистрация

Восстановить пароль
Повторная активизация e-mail

Купить рекламу на форуме - 42 тыс руб за месяц

Ответ
 
Опции темы Поиск в этой теме
Старый 19.10.2012, 14:45   #1
mikhea
Пользователь
 
Регистрация: 17.01.2007
Сообщений: 26
По умолчанию Мерцание кнопок внутри StringGrid

Добрый день!
Столкнулся с такой проблемой. Есть StringGrid, внутри него несколько столбцов с кнопками, на каждой кнопке картинка. Количество строк динамически изменяется в процессе работы с программой (их можно добавлять, удалять и т.д.), соответственно, количество кнопок тоже меняется. Так вот, при прокрутке таблицы и перемещнии строк кнопки начинают жутко мерцать, а сама форма - тормозить и подвисать. Причем чем больше строк, тем более выражена проблема (что, впрочем, вполне логично). Кто-нибудь знает, можно ли как-нибудь уменьшить мерцание и торможение? Возможно, у меня не очень хорошо написан обработчик OnTopLeftChanged.
mikhea вне форума Ответить с цитированием
Старый 19.10.2012, 14:48   #2
Luuzuk
Форумчанин
 
Аватар для Luuzuk
 
Регистрация: 18.01.2012
Сообщений: 975
По умолчанию

Цитата:
Возможно, у меня не очень хорошо написан обработчик OnTopLeftChanged.
Возможно.

Еще попробуйте свойство DoubleBuffered установить в True
Благодарить в репутацию. Проклинать — туда же
Luuzuk вне форума Ответить с цитированием
Старый 19.10.2012, 15:01   #3
psycho-coder
Участник клуба
 
Аватар для psycho-coder
 
Регистрация: 06.04.2009
Сообщений: 1,524
По умолчанию

Есть еще грязный хак. Поставить alfa blend в true для формы
Но он не всегдя помогает
psycho-coder вне форума Ответить с цитированием
Старый 19.10.2012, 15:03   #4
mikhea
Пользователь
 
Регистрация: 17.01.2007
Сообщений: 26
По умолчанию

DoubleBuffered в True установлен (при создании формы).
Вот мой обработчик OnTopLeftChanged:
Код:
procedure TfrmMy.grdMyTopLeftChanged(Sender: TObject);
var
  Rect: TRect;
  i, j: integer;
  gCol: integer;      //Столбец таблицы, соотв. создаваемой кнопке
begin
  try
    for i:=0 to grdMy.RowCount-1 do
      for j:=0 to 5 do
      begin
        if (j = 0) or (j = 1) then
          gCol := j+1
        else
          gCol := j+3;
        Rect := grdMy.CellRect(gCol, i);
        if (grdMy.Objects[gCol, i] is TControl) then
          with TControl(grdMy.Objects[gCol, i]) do
            if (Rect.Right = Rect.Left) then
              Visible := False
            else
            begin
              if ((Rect.Top = 0) and (Rect.Bottom <> 0) and (i <> 0)) then
                continue;      //Избавляемся от ошибки, периодически возникающей
                               //на границе видимой области
              InflateRect(Rect, -1, -1);
              OffsetRect(Rect, grdMy.Left + 2, grdMy.Top + 2);
              BoundsRect := Rect;
              Visible := True;
            end;
      end;
  except
  end;
end;
mikhea вне форума Ответить с цитированием
Старый 19.10.2012, 15:06   #5
mikhea
Пользователь
 
Регистрация: 17.01.2007
Сообщений: 26
По умолчанию

Цитата:
Сообщение от psycho-coder Посмотреть сообщение
Есть еще грязный хак. Поставить alfa blend в true для формы
Но он не всегдя помогает
Попробовал, стало еще хуже. Таблица при прокрутке еле ползает.
mikhea вне форума Ответить с цитированием
Старый 19.10.2012, 15:08   #6
psycho-coder
Участник клуба
 
Аватар для psycho-coder
 
Регистрация: 06.04.2009
Сообщений: 1,524
По умолчанию

Цитата:
Вот мой обработчик OnTopLeftChanged:
А если заюзать "ручной backbuffer"? То есть вы отрисовываете в памяти в bitmap таблицу, а потом просто выводите на фронт? С реализацией не помогу, на Delphi уже больше двух лет ничего не писал.
psycho-coder вне форума Ответить с цитированием
Старый 19.10.2012, 15:23   #7
mikhea
Пользователь
 
Регистрация: 17.01.2007
Сообщений: 26
По умолчанию

Цитата:
Сообщение от psycho-coder Посмотреть сообщение
А если заюзать "ручной backbuffer"? То есть вы отрисовываете в памяти в bitmap таблицу, а потом просто выводите на фронт? С реализацией не помогу, на Delphi уже больше двух лет ничего не писал.
В принципе, понял, о чем Вы говорите, но никогда подобного не делал. Попробую. Если кто-то подскажет поконкретнее, как это реализовать, буду очень благодарен.
Вообще, насколько я понял, проблема в том, что при прокрутке TopLeftChanged вызывается несколько раз, т.е. когда зажимаешь стрелку на полосе прокрутки, таблица начинает двигаться прерывисто, по нескольку строк, ну и TopLeftChanged вызывается при каждом рывке, и все мерцает. Я бы даже сказал, что это не мерцание, а размазанность какая-то. Кстати, а можно отловить нажатие мыши на полосе прокрутки? А то может стоит при нажатии просто делать невидимыми все кнопки, а потом при отпускании опять видимыми.
mikhea вне форума Ответить с цитированием
Старый 19.10.2012, 15:40   #8
Serge_Bliznykov
Старожил
 
Регистрация: 09.01.2008
Сообщений: 26,229
По умолчанию

так, в порядке бреда..
а что если завести глобальную переменную и сохранять туда время, когда предыдущий раз вызывался обработчик TopLeftChanged (через GetTickCount, например: var CountTicks : DWORD; CountTicks := GetTickCount().
и в начале обработчика поставить проверку, если время от предыдущего вызова прошло меньше заданной константы - выходить из процедуры:
Код:
procedure TfrmMy.grdMyTopLeftChanged(Sender: TObject);
var
  Rect: TRect;
  i, j: integer;
  gCol: integer;      //Столбец таблицы, соотв. создаваемой кнопке
begin
  if GetTickCount()< (CountTicks+1000) then Exit; {ушли, если ещё секунда не прошла...}

  CountTicks :=  GetTickCount(); {сохранили очередное время выполнения обработчика...}
Ну и ещё одно. Не буду категорически утверждать, НО! Попробуйте написать код так, чтобы избежать необходимость использования try except - это тоже явно не добавляет быстродействия вашему обработчику.

Попробуйте, вдруг поможет...
Serge_Bliznykov вне форума Ответить с цитированием
Старый 19.10.2012, 22:02   #9
mikhea
Пользователь
 
Регистрация: 17.01.2007
Сообщений: 26
По умолчанию

Цитата:
Сообщение от Serge_Bliznykov Посмотреть сообщение
а что если завести глобальную переменную и сохранять туда время, когда предыдущий раз вызывался обработчик TopLeftChanged (через GetTickCount, например: var CountTicks : DWORD; CountTicks := GetTickCount().
и в начале обработчика поставить проверку, если время от предыдущего вызова прошло меньше заданной константы - выходить из процедуры:
К сожалению, не вариант. Обработчик TopLeftChanged должен срабатывать хотя бы на последнем этапе прокрутки, иначе не происходит установка видимости/невидимости нужных кнопок. Можно было бы вызывать его в момент отпускания клавиши мыши с полосы прокрутки, но не представляю, как это сделать. Только если по координатам вычислять, но вряд ли это будет точно.
mikhea вне форума Ответить с цитированием
Старый 19.10.2012, 22:54   #10
ReportCube
Форумчанин
 
Аватар для ReportCube
 
Регистрация: 11.03.2011
Сообщений: 426
По умолчанию

Вопрос: если у Вас grdMy.RowCount будет равен миллиону, то при всяком скроллировании в цикле будет обрабатываться миллион кнопок?
ReportCube вне форума Ответить с цитированием
Ответ


Купить рекламу на форуме - 42 тыс руб за месяц



Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
Обработка одномерных массивов, СИ. задание внутри, и написанный мною текст программы тоже внутри. кое-что нужно исправить.. Амелия Общие вопросы C/C++ 6 02.04.2012 20:03
Мерцание ZBEP Общие вопросы Delphi 3 09.04.2011 15:14
Нахождение слов-анаграмм, Ошибка выдается. Задание внутри. Код внутри. TYMON Общие вопросы .NET 2 22.11.2010 21:07
Мерцание StringGrid (CLX) SpaceIQ Общие вопросы Delphi 6 13.07.2009 15:21
Как раскрасить ячейку внутри StringGrid. GarfieldX Общие вопросы Delphi 5 14.02.2008 21:59