Delphi RIO 10.3.1 FMX TListView'ItemClickEx'单次点击会发生2次。

问题描述 投票:0回答:1

我试图实现一个 "toggle "功能,当点击tlistview项目时。但在测试时,我注意到点击事件会被触发2次,而且是用不同的参数点击。这是 "按设计工作 "吗?我只是在一个空窗体中添加了一个列表视图,并实现了 "ItemClickEx "事件。我找不到一个变通的方法来解决我的toggle问题......除了实现一个定时器来跟踪点击,并忽略过早的第二次点击......(在看堆栈跟踪时,似乎FMX框架也可以使用延迟事件)

我也测试了onitemclick事件,这个事件确实只触发了一次......所以我也许可以用它来实现简单的变通。但不是很好,我需要 "前 "版本,以及最终,我需要从我的列表中添加删除项目,这是建议只有从 "前 "版本,根据文档。

祝贺德克

delphi firemonkey mouseclick-event tlistview
1个回答
2
投票

更新 请看下面的更新部分,它是基于OP在他自己的回答中的观察。

下面的最小项目并没有表现出你所描述的行为。

如果我点击ListView1中的任何一个项目,则会出现 ItemClickedCount 变量只能递增1,这一点在表单的标题中得到了证实(如果我双击表单。ItemClickedCount增量为2,正如预期的那样)。)

要实现你的切换,简单地切换一个布尔值就足够了,或者你可以简单地从是否是 ItemClickedCount 是奇数或偶数。

所以,我认为你所描述的行为一定是来自于你的q中没有提到的代码的某一部分。显然,找出原因的方法是反复简化你的表单和它的代码。 祝您好运

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 在过程TListViewBase.ProcessIncident(const Entry: TDelayedIncidentEntry)中,被2003行调用(Case Entry.Incident of...TDelayedIncident.ClickEvent:)。

显然,要想被调用两次,必须有两个这样的 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的属性设置来避免这种情况并不明显,但可能是这样。 然而,仍然有一个简单的变通方法,可以包含在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
投票

谢谢你的意见。

你是正确的,如果你只添加一个TListview,并在代码中填充TListviewitems,并将项目外观默认为ListItem,那么在我的设置中,该事件只发生一次。然而,只要我将ItemAppearance改为 "自定义",并且只让Glyphbutton可见,它就会触发2次。 这似乎与实际的 itemobjects(Text , Glyph , Accessory)是否重叠无关(所以并不是说 glyphbutton 的点击事件也会被传递到 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

问候德克

© www.soinside.com 2019 - 2024. All rights reserved.