【问题标题】:Delphi RIO 10.3.1 FMX TListView 'ItemClickEx' fires 2 for single clickDelphi RIO 10.3.1 FMX TListView 'ItemClickEx' 触发 2 次单击
【发布时间】:2020-05-03 14:03:20
【问题描述】:

我试图在单击 tlistview 项目时实现“切换”功能。但是在测试时,我注意到单击事件 get 被触发了 2 次,单击/点击具有相同的参数.. 我现在在 Windows 上测试这个。 这是“按设计工作”吗?

我只在一个空表单中添加了一个列表视图并实现了“ItemClickEx”事件。
我找不到切换的解决方法..除了实现一个计时器来跟踪点击并很快忽略第二次点击... (看起来 FMX 框架在查看堆栈跟踪时也适用于延迟事件)

我还测试了 onitemclick 事件,这个事件只触发一次。 ..所以我可以用它来实现简单的解决方法。但不好,我需要'ex'版本以及最终,我需要从我的列表中添加/删除项目,根据文档,我只推荐从'ex'版本中推荐。

问候 德克

【问题讨论】:

    标签: delphi firemonkey mouseclick-event tlistview


    【解决方案1】:

    更新请参阅下面的更新部分,该部分基于 OP 在他自己的回答中的观察。

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

    如果我单击 ListView1 中的任何项目,ItemClickedCount 变量只会增加一, 正如表单标题上显示的那样(如果我双击表单,ItemClickedCount 按预期增加 2)。

    要实现您的切换,只需切换一个布尔值就足够了,或者您可以简单地 从ItemClickedCount 是奇数还是偶数得出切换状态。

    所以,我认为您描述的行为必须来自 soe 部分 您的 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 由第 2003 行调用(Case Entry.Incident of ... TDelayedIncident.ClickEvent:) 在过程 TListViewBase.ProcessIncident(const Entry: TDelayedIncidentEntry);

    显然,要被调用两次,每次点击必须有两个这样的Incidents,所以我随后研究了这些事件是如何添加到正在处理的任何列表/队列中的。于是我在第 1949 行查看了procedure TListViewBase.StartIncident(const Incident: TDelayedIncident; const Triggered: Boolean; const TimeToWait: Single; const CustomData: NativeInt);

    每次鼠标点击后,这会被调用两次:

    • 第一次查看调用堆栈时,调用源自第 4083 行的 procedure TListViewBase.SetNewItemIndex(const NewIndex: Integer)

    • 第二次,来自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;
    

    我想知道如何将这种重复数据删除处理连接到可以包含在源单元中的插入器类中。如果我能想到一个干净的方法,我可能会在稍后添加它。

    【讨论】:

    • 您好,我检查过了,请在下面查看我的发现
    • 您好,谢谢您的确认!它总是有助于评估您自己的理智水平:-)。解决方法到位。我确实认为它应该被归类为“错误”。有多个事件可能没问题(因为项目上有多个子组件,但参数不一样)。 1 点击就是 1 点击,问候。
    【解决方案2】:


    谢谢你的意见。

    你是对的,如果你只添加一个 TListview 并在代码中用 TListviewitems 填充它,并将项目外观默认为 ListItem,那么该事件在我的设置中也只会触发一次。
    但是,一旦我将 ItemAppearance 更改为“custom”,并且仅使 Glyphbutton 可见,它就会触发 2 次。
    看起来这与实际的 itemobjects( Text 、 Glyph 、 Accessory )是否重叠是无关的(所以并不是说 glyphbutton click 事件也再次传递给 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
    
    

    问候 德克

    【讨论】:

      猜你喜欢
      • 2017-10-03
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多