Delphi RIO 10.3.1 FMX TListView 'ItemClickEx' запускает 2 для одного клика - PullRequest
0 голосов
/ 03 мая 2020

Я пытаюсь реализовать функцию «переключения» при нажатии на элемент tlistview. Но при тестировании я замечаю, что событие click срабатывает 2 раза одним щелчком / касанием с параметрами IDENTICAL .. Я сейчас тестирую это на windows. Это «работает как задумано»?
Я только добавил просмотр списка в пустую форму и реализовал событие ItemClickEx. Я не мог найти обходной путь к своему переключению ... за исключением реализации таймера, который бы отслеживал щелчки и игнорировал второй щелчок до скорого ... (похоже, среда FMX также работает с отложенными событиями при просмотре трассировки стека). )

Я также протестировал событие onitemclick, и оно срабатывает только один раз. .. так что я мог бы использовать его для реализации простого обходного пути. Но не приятно, мне нужна версия «ex», а также, в конце концов, мне нужно добавить / удалить элементы из моего списка, что рекомендуется только из версии «ex», согласно документации.

С уважением, Дирк

Ответы [ 2 ]

2 голосов
/ 03 мая 2020

Обновление Пожалуйста, смотрите раздел Обновления ниже, который основан на наблюдениях ОП в его собственном ответе.

Минимальный проект ниже не демонстрирует поведение, которое вы описываете.

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

Для реализации вашего переключения достаточно просто переключить логическое значение, иначе вы можете просто получить состояние переключения из того, является ли ItemClickedCount нечетным или четным.

Итак, я думаю, что описанное вами поведение должно исходить из той части вашего кода, которая не упомянута в вашем вопросе. Очевидно, что способ определить причину состоит в том, чтобы итеративно упростить вашу форму и ее код. Удачи!

procedure TForm1.BuildList;
var
  LItem : TListViewItem;
  ListItemText : TListItemText;
  Index : Integer;
begin
  ListView1.BeginUpdate;
  try
    ListView1.Items.Clear;
    ListView1.ItemAppearanceObjects.ItemEditObjects.Text.TextVertAlign := TTextAlign.Leading;
    for Index := 0 to 19 do begin
      LItem := ListView1.Items.Add;
      LItem.ButtonText := 'Hello';
      LItem.Text := 'Row: ' + IntToStr(Index);
      LItem.Height := 25;
      ListItemText := TListItemText.Create(LItem);
      ListItemText.PlaceOffset.X := 100;
      ListItemText.PlaceOffset.Y := 25 * (Index - 1);
      ListItemText.Name := 'Name' + IntToStr(Index);
    end;
  finally
    ListView1.EndUpdate;
  end;
end;

procedure TForm1.ListView1ItemClickEx(const Sender: TObject; ItemIndex: Integer;
  const LocalClickPos: TPointF; const ItemObject: TListItemDrawable);
begin
  Inc(ItemClickedCount);
  Caption := IntToStr(ItemClickedCount);
end;

procedure TForm1.Button1Click(Sender: TObject);
begin
  BuildList;
end;

Обновление Отвечая на ваш комментарий + ответ, да, я вижу, что ListView1ItemClickEx вызывается дважды за каждый щелчок мышью. Я рассмотрел, почему это происходит, и это кажется преднамеренным, хотя почему так и должно быть, для меня не очевидно.

Глядя на источник FMX.ListView (я делаю это в Сиэтле, чтобы номера ваших строк могли различаться), ListView1ItemClickEx вызывается в строке 2003 (Case Entry.Incident of ... TDelayedIncident.ClickEvent :) в процедуре TListViewBase.ProcessIncident (const Entry: TDelayedIncidentEntry);

Очевидно, чтобы вызываться дважды, должно быть два таких Incidents на клик, поэтому я посмотрел, как эти инциденты добавляются в любой обрабатываемый список / очередь. Затем я посмотрел на procedure TListViewBase.StartIncident(const Incident: TDelayedIncident; const Triggered: Boolean; const TimeToWait: Single; const CustomData: NativeInt); в строке 1949.

После каждого щелчка мыши это вызывается дважды:

  • Первый раз, глядя на стек вызовов, Вызов происходит в procedure TListViewBase.SetNewItemIndex(const NewIndex: Integer) в строке 4083.

  • Второй раз, он изнутри procedure TListViewBase.MouseUp(Button: TMouseButton; Shift: TShiftState; X, Y: Single).

Это не очевидно для меня, как избежать этого с помощью настроек свойств TListView, но это может быть. Тем не менее, в обработчике ListView1ItemClickEx есть простой обходной путь:

procedure TForm1.ListView1ItemClickEx(const Sender: TObject; ItemIndex: Integer;
  const LocalClickPos: TPointF; const ItemObject: TListItemDrawable);
var
 LItem : TListViewITem ;
begin
  Inc(ItemClickedCount);
  if not Odd(ItemClickedCount) then
    Exit;

  Caption := IntToStr(ItemClickedCount);

  LITem := ListView1.Items[ItemIndex];
  LItem.Tag :=  LItem.Tag + 1 ;

  LItem.Text := LItem.Text +  ' ' + LItem.Tag.ToString + 'clicks';

end;

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

0 голосов
/ 04 мая 2020

Спасибо за ваш вклад.

Вы правы, если вы только добавляете TListview и заполняете его TListviewitems в коде и оставляете внешний вид элемента по умолчанию как ListItem, событие также запускается только один раз в моей настройке. Однако, как только я изменяю ItemAppearance на 'custom' и, кроме того, только делаю Glyphbutton видимым, он срабатывает 2 раза. Кажется, это не зависит от того, перекрываются или нет фактические предметные объекты (Текст, Глиф, Аксессуар) (но это не так, например, событие нажатия кнопки глифа также передается еще раз в событие itemclick) Также не важно, где именно я нажимаю, всегда срабатывает 2 раза Видите ли вы такое же поведение?

type
  TForm1 = class(TForm)
    Panel1: TPanel;
    Button1: TButton;
    ListView1: TListView;
    procedure Button1Click(Sender: TObject);
    procedure ListView1ItemClickEx(const Sender: TObject; ItemIndex: Integer;
      const LocalClickPos: TPointF; const ItemObject: TListItemDrawable);
  private
    { Private declarations }
  public
    { Public declarations }
  end;

procedure TForm1.Button1Click(Sender: TObject);
var
 i : integer ;
 LItem : TListViewItem ;

 lListView : TListView ;
begin


  // Here we should create the overal listview structure
  // The visual appearance of items need to be done in updateobjects
  // Only this one is always (re)triggered !!

  lListView := ListView1;
  lListView.BeginUpdate;
  try
   for i := 0 to 10 - 1 do begin
     LItem := lListView.Items.Insert(i);
     LItem.Text := 'Test' + I.ToString;
   end;
  finally
    lListView.EndUpdate;
  end;


end;

procedure TForm1.ListView1ItemClickEx(const Sender: TObject; ItemIndex: Integer;
  const LocalClickPos: TPointF; const ItemObject: TListItemDrawable);
var
 LItem : TListViewITem ;
begin

LITem := ListView1.Items[ItemIndex];
LItem.Tag :=  LItem.Tag + 1 ;

LItem.Text := LItem.Text +  ' ' + LItem.Tag.ToString + 'clicks';

end;

...

  object ListView1: TListView
    ItemAppearanceClassName = 'TCustomizeItemObjects'
    ItemEditAppearanceClassName = 'TCustomizeItemObjects'
    HeaderAppearanceClassName = 'TListHeaderObjects'
    FooterAppearanceClassName = 'TListHeaderObjects'
    Align = Client
    Size.Width = 640.000000000000000000
    Size.Height = 439.000000000000000000
    Size.PlatformDefault = False
    TabOrder = 1
    ItemAppearanceObjects.ItemObjects.Text.Width = 100.000000000000000000
    ItemAppearanceObjects.ItemObjects.Text.Height = 44.000000000000000000
    ItemAppearanceObjects.ItemObjects.Text.PlaceOffset.X = 168.000000000000000000
    ItemAppearanceObjects.ItemObjects.Detail.Width = 230.000000000000000000
    ItemAppearanceObjects.ItemObjects.Detail.Height = 44.000000000000000000
    ItemAppearanceObjects.ItemObjects.Detail.PlaceOffset.X = 230.000000000000000000
    ItemAppearanceObjects.ItemObjects.Accessory.Visible = True
    ItemAppearanceObjects.ItemObjects.GlyphButton.Width = 31.000000000000000000
    ItemAppearanceObjects.ItemObjects.GlyphButton.Height = 30.000000000000000000
    ItemAppearanceObjects.ItemObjects.GlyphButton.Visible = True
    ItemAppearanceObjects.ItemObjects.GlyphButton.PlaceOffset.X = 24.000000000000000000
    OnItemClickEx = ListView1ItemClickEx
  end

regards Dirk

...