Карта сайта Kansoftware
НОВОСТИУСЛУГИРЕШЕНИЯКОНТАКТЫ
KANSoftWare

Синхронизация данных между OnMeasureItem и OnGetText в TVirtualStringTree

Delphi , Синтаксис , Деревья

TVirtualStringTree: Синхронизация данных между OnMeasureItem и OnGetText

При работе с компонентом TVirtualStringTree может возникнуть проблема, когда данные, используемые для измерения высоты узла в событии OnMeasureItem, меняются к моменту печати данных в событии OnGetText. Это происходит из-за того, что события обрабатываются в следующем порядке:

  1. OnMeasureItem для всех непроинициализированных узлов
  2. OnGetText для всех узлов

Однако sometimes, especially when data is updated by another thread, we need to ensure that the data used for measurement in OnMeasureItem is the same as the data printed in OnGetText. In this case, we need to synchronize the data obtained between these two events.

Описание проблемы

У меня есть массив, который содержит данные, отображаемые в TVirtualStringTree. Этот массив является потокобезопасным и блокируемым, и растет в другом потоке. Проблема заключается в том, что когда VST выполняет событие OnMeasureItem для измерения высоты узла, данные, используемые для измерения, могут измениться к моменту печати данных с помощью события OnGetText.

Я проверил порядок выполнения событий, и он не подходит для моего дизайна. Сначала вызывается событие OnMeasureItem для всех непроинициализированных узлов, а затем начинаются вызовы событий OnGetText. Другими словами, если у нас есть 3 узла, события будут запущены в следующем порядке:

  1. OnMeasureItem для узла 1
  2. OnMeasureItem для узла 2
  3. OnMeasureItem для узла 3
  4. OnGetText для узла 1
  5. OnGetText для узла 2
  6. OnGetText для узла 3

Мне нужен такой порядок, чтобы я мог заблокировать:

  1. OnMeasureItem для узла 1
  2. OnGetText для узла 1
  3. OnMeasureItem для узла 2
  4. OnGetText для узла 2
  5. OnMeasureItem для узла 3
  6. OnGetText для узла 3

Какой лучший способ поддерживать синхронизацию данных, полученных между событиями OnMeasureItem и OnGetText?

Я не хочу блокировать мой массив во время всех событий OnMeasureItem() и OnGetText().

Альтернативный ответ

У меня есть массив, который содержит данные, отображаемые в TVirtualStringTree. Этот массив является потокобезопасным и блокируемым, и растет в другом потоке. Проблема заключается в том, что когда VST выполняет событие OnMeasureItem для измерения высоты узла, данные, используемые для измерения, могут измениться к моменту печати данных с помощью события OnGetText.

Я проверил порядок выполнения событий, и он не подходит для моего дизайна. Сначала вызывается событие OnMeasureItem для всех непроиinitialized узлов, а затем начинаются вызовы событий OnGetText. Другими словами, если у нас есть 3 узла, события будут запущены в следующем порядке:

  1. OnMeasureItem для узла 1
  2. OnMeasureItem для узла 2
  3. OnMeasureItem для узла 3
  4. OnGetText для узла 1
  5. OnGetText для узла 2
  6. OnGetText для узла 3

Мне нужен такой порядок, чтобы я мог заблокировать:

  1. OnMeasureItem для узла 1
  2. OnGetText для узла 1
  3. OnMeasureItem для узла 2
  4. OnGetText для узла 2
  5. OnMeasureItem для узла 3
  6. OnGetText для узла 3

Какой лучший способ поддерживать синхронизацию данных, полученных между событиями OnMeasureItem и OnGetText?

Я не хочу блокировать мой массив во время всех событий OnMeasureItem() и OnGetText().

Подтвержденный ответ

Один из подходов к решению этой проблемы заключается в том, чтобы принудительно запустить измерение высоты узла, удалив флаг vsHeightMeasured из состояния узла и вызвав метод MeasureItemHeight непосредственно из события OnGetText. Это снова запустит событие OnMeasureItem. Проблема в том, что OnMeasureItem не должен запускаться более одного раза при изменении текста узла, но все же необходимо обрабатывать его из-за Scrolling Stuff.

Поэтому одним из решений может быть добавление собственного флага NodeMeasured в структуру данных и сброс его всякий раз, когда текст узла изменится (когда некоторые данные в элементе журнала изменятся), и установка его после прохождения события OnGetText с принудительным измерением высоты узла. Вот псевдокод:

procedure TForm1.VirtualStringTreeGetText(Sender: TBaseVirtualTree;
  Node: PVirtualNode; Column: TColumnIndex; TextType: TVSTTextType;
  var CellText: string);
begin
  ThreadList.LockList;
  try
    // Проверьте, не установлен ли собственный флаг, который указывает, что текст является новым,
    // что данные изменились с последнего посещения в OnGetText, и если да, принудительно запустите измерение узла,
    // чтобы установить текущую высоту узла, и установите этот флаг на True, чтобы запомнить, что мы уже сделали это
    if not ThreadList.Items[Node.Index].NodeMeasured then
    begin
      // Фальшивое измерение узла, удаление флага измеренной высоты
      Exclude(Node.States, vsHeightMeasured);
      // Это запустит событие OnMeasureItem снова из-за удаленного флага vsHeightMeasured из состояния узла
      VirtualStringTree.MeasureItemHeight(VirtualStringTree.Canvas, Node);
      // Установите флаг NodeMeasured, чтобы запомнить, что мы измерили узел
      ThreadList.Items[Node.Index].NodeMeasured := True;
    end;
    // Здесь установите текст узла и разблокируйте ваш потокобезопасный список
    CellText := ThreadList[Node.Index].SomeText;
  finally
    ThreadList.UnlockList;
  end;
end;

И в вашем потоке, когда данные изменятся, вам нужно установить этот флаг NodeMeasured на False.

if LogHasChanged then
begin
  ThreadList.LockList;
  try
    ThreadList.Items[X].NodeMeasured := False;
    ThreadList.Items[X].SomeText := 'Something new';
  finally
    ThreadList.UnlockList;
  end;
end;

Заключение

Синхронизация данных между событиями OnMeasureItem и OnGetText в TVirtualStringTree может быть сложной задачей, но добавление собственного флага NodeMeasured в структуру данных и принудительное измерение высоты узла в событии OnGetText может быть одним из решений этой проблемы. Важно помнить, что это всего лишь одно из многих возможных решений, и вам может потребоваться адаптировать его в зависимости от ваших конкретных потребностей и обстоятельств.

Создано по материалам из источника по ссылке.

Проблема заключается в синхронизации данных между событиями `OnMeasureItem` и `OnGetText` в компоненте `TVirtualStringTree`, когда данные, используемые для измерения высоты узла в `OnMeasureItem`, могут меняться к моменту печати данных в `OnGetText`. Нужн


Комментарии и вопросы

Получайте свежие новости и обновления по Object Pascal, Delphi и Lazarus прямо в свой смартфон. Подпишитесь на наш Telegram-канал delphi_kansoftware и будьте в курсе последних тенденций в разработке под Linux, Windows, Android и iOS




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


:: Главная :: Деревья ::


реклама


©KANSoftWare (разработка программного обеспечения, создание программ, создание интерактивных сайтов), 2007
Top.Mail.Ru

Время компиляции файла: 2024-12-22 20:14:06
2025-01-28 07:03:56/0.0037147998809814/0