Перейти к содержанию
Fire Monkey от А до Я
  • 0

Странное поведение TListBox при попытке прокрутки до конца списка


AngryOwl

Вопрос

Привет друзья!

Возникла странная ситуация при работе с TListBox. А именно - при попытке прокрутки списка в его конец.

Условно:

- есть список итемов (сообщения чата);

- загрузка сообщений происходит в процедуре "синхронизированной" с главным потоком и заключена в TListBox(listbox1).BeginUpdate  и TListBox(listbox1).EndUpdate;

- все замечательно грузится

НО! После загрузки Итемов требуется прокрутить список в его конец. И вот тут начинаются "приколы".

Как только не пытаться прокрутить список в его конец (разные способы, см.ниже) - всегда получается, что список прокручивается до конца, но немного "откатывается" вверх. Размер его автоматического скролла "обратно" зависит от количества Item в TListBox! Чем больше кол-во Item - тем больше назад откатывается скролл.

Способы прокрутки в конец списка - значения не имеют. Всегда одно и то же.

procedure TChatListBoxEx.ScrollToLast;
var
  Item: TListBoxItem;
begin
// ВАРИАНТ 1
  Item := ListItems[Items.Count - 1];
  if Assigned(Item) then
    ScrollToItem(Item);

// ВАРИАНТ 2
  ViewportPosition:= TPointF.Create(0, Item.ParentedRect.Top);

// ВАРИАНТ 3
  ScrollBy(0, ViewportPosition.Y - Item.ParentedRect.Top);

// ВАРИАНТ 4
  BeginUpdate;
  try
    ItemIndex := Items.Count - 1;
  finally
    EndUpdate;
  end;
end;

Предупреждая ваши вопросы, сразу скажу - пробовал и другие варианты, просто перечислять не стал все. Пробовал и эмитировать нажатие клавиши END при "активном" списке.

Все синхронизируется, типа 

TThread.Synchronize(nil, listbox1.ScrollToLast);

Эффект всегда один и тот же...

НО! Если загрузить список, независимо от кол-ва элементов списка, а потом в программе вызвать ScrollToLast, подождав некоторое время, а не сразу, например по нажатию на какую-нибудь кнопку, то список прокрутится в конец НОРМАЛЬНО!

Будьте добры - кто сталкивался с подобной ситуацией, или кто что-то может посоветовать?

Или наши Гуру смогут ответить на этот вопрос?

Видео, чтобы было понятнее что происходит, прилагаю.

RAD Studio 10.1 Berlin (эффект наблюдается на всех версиях Windows - XP, Vista, 7, 8, 10. На других ОС пока не пробовал...)

Заранее благодарен!

P.S. Возник вопрос (как вариант решения проблемы) - как узнать, что произошло событие окончания отрисовки TListBox? А именно - список заполнился, выполнилась отрисовка и можно прокручивать.

Изменено пользователем AlexG
Ссылка на комментарий

Рекомендуемые сообщения

  • 0
19 минут назад, AlexG сказал:

подождав некоторое время

Ну, с моей стороны будет костылирование, а не решение, но...

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

Например:

TTask.Run(TThread.Queue(ScrollToLast));

 

Ссылка на комментарий
  • 0
8 минут назад, kami сказал:

Ну, с моей стороны будет костылирование, а не решение, но...

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

Например:


TTask.Run(TThread.Queue(ScrollToLast));

 

Спасибо! Но, к сожалению, эффект тот же...

Ссылка на комментарий
  • 1
  • Модераторы

не смог воспроизвести вашу ситуацию, есть подозрение на стиль. попробуйте при добавлении Item'a, прогрузить стиль вручную

LBScroll.zip

Ссылка на комментарий
  • 0
3 часа назад, ZuBy сказал:

не смог воспроизвести вашу ситуацию, есть подозрение на стиль. попробуйте при добавлении Item'a, прогрузить стиль вручную

LBScroll.zip

Во-первых - спасибо за подсказку (прогрузить стили)!
А во-вторых - решение конечно еще тот "костыль", но работает.

Перед тем как прокрутить TListBox в конец (любым способом), потребовалось пробежать по всем Итемам и применить им стиль!

for i := 0 to TListBox(Sender).Items.Count - 1 do
  TListBox(Sender).ListItems[i].ApplyStyleLookup;

И только после это - все работает как надо. И никак иначе...

Есть, конечно, над чем поработать - например на скоростью. Но пока меня решение устраивает.

Спасибо! Вопрос решен!

 

Изменено пользователем AlexG
Ссылка на комментарий

Присоединяйтесь к обсуждению

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

Гость
Ответить на вопрос...

×   Вставлено с форматированием.   Вставить как обычный текст

  Разрешено использовать не более 75 эмодзи.

×   Ваша ссылка была автоматически встроена.   Отображать как обычную ссылку

×   Ваш предыдущий контент был восстановлен.   Очистить редактор

×   Вы не можете вставлять изображения напрямую. Загружайте или вставляйте изображения по ссылке.

×
×
  • Создать...