【问题标题】:Get position of object in a list in Delphi?在Delphi的列表中获取对象的位置?
【发布时间】:2011-04-26 12:33:41
【问题描述】:

我想知道如何在创建的列表中获取某个对象的位置。 可以说它就像一个图形列表,您可以在其中单击对象。 假设您右键单击一个对象并单击“刷新”,我如何获取该对象的位置,以便在刷新整个列表后(由于某种原因用清除列表刷新)我回到列表中的相同位置?如果列表的长度为 1000 个对象,则刷新后尝试向下滚动到相同位置会很麻烦。

代码使用 Tobject 但我可以做类似的事情吗 位置:=整数(TObject。“指针信息???”); 之后,当程序刷新时 比如将视图的位置设置为指针 像 currentview(pointer) 或类似的东西?

其实不必是同一个对象,但列表的同一个“视图”会更好。

提前致谢

【问题讨论】:

  • 您在寻找TListItem.Index吗?你在position := integer(TObject."pointerinfo????");失去了我
  • 什么是“图形列表”和“对象”?您尝试使用哪些类?可以展示一下代码示例吗?

标签: delphi list listview tobject


【解决方案1】:

如果刷新会再次以相同的顺序为您提供相同的列表,那么请不要费心去发现有关该对象的任何信息。只需存储列表控件的ItemIndex 属性,该属性表示当前选中的项。

如果刷新可能会给你一个不同的列表,那么之后你想要的对象可能不在同一个位置,所以仅仅记住ItemIndex 是不够的。在这种情况下,您需要找到对象的新位置。如何做到这一点取决于列表控件的功能以及它如何公开与每个位置关联的对象。例如,如果您有一个TListBox,那么Items 属性就是一个TStrings 对象,您可以检查Objects 数组的每个值,直到找到您想要的对象。存储对象引用的值,然后搜索它。像这样的:

procedure Refresh;
var
  CurrentSelection: TObject;
  ObjectPosition: Integer;
  i: Integer;
begin
  if List.ItemIndex >= 0 then
    CurrentSelection := List.Strings.Objects[List.ItemIndex]
  else
    CurrentSelection = nil;
  RefreshList;
  ObjectPosition := -1;
  if Assigned(CurrentSelection) then begin
    for i := 0 to Pred(List.Count) do begin
      if List.Strings.Objects[i] = CurrentSelection then begin
        ObjectPosition := i;
        break;
      end;
    end;
  end;
  if ObjectPosition = -1 then
    // Object isn't in refreshed list
  else
    // It is.
end;

最后一种可能性是,刷新实际上根本不会保留相同的对象。所有先前的对象都被销毁,并生成一个新的对象列表。在这种情况下,您必须记住原始对象的某些识别特征,以便找到代表相同事物的新对象。像这样的:

var
  CurrentObject, Person: TPerson;
  CurrentName: string;
  i, ObjectPosition: Integer;
begin
  if List.ItemIndex >= 0 then begin
    CurrentObject := List.Strings.Objects[List.ItemIndex] as TPerson;
    CurrentName := CurrentObject.Name;
  end else
    CurrentName = '';
  RefreshList;
  ObjectPosition := -1;
  if CurrentName <> '' then begin
    for i := 0 to Pred(List.Count) do begin
      Person := List.Strings.Objects[i] as TPerson;
      if Person.Name = CurrentName then begin
        ObjectPosition := i;
        break;
      end;
    end;
  end;
  if ObjectPosition = -1 then
    // Object isn't in refreshed list
  else
    // It is.
end;

在所有这些情况下,您应该意识到对象在列表中的位置实际上并不是对象的属性。相反,它是列表的一个属性,这就是为什么列表在所有代码中比对象发挥更大的作用。实际上没有任何“指针信息”可以从对象中获取,因为对象通常不知道它甚至 in 一个列表,所以它肯定不会知道它相对于所有对象的位置列表中的其他项目。

确定对象在列表中的位置后,您需要将其滚动到视图中。对于TListBox,一个简单的方法是设置它的TopIndex属性:

List.TopIndex := ObjectPosition;

最后,如果你根本不关心当前的对象,而只是想恢复当前的滚动位置,那就更简单了:

procedure Refresh;
var
  CurrentPosition: Integer;
begin
  CurrentPosition := List.TopIndex;
  RefreshList;
  List.TopIndex := CurrentPosition;
end;

【讨论】:

  • TStrings 类实际上有一个IndexOfObject 方法,它可以更快地找到对象(只要对象地址没有改变)。在较新版本的 Delphi 中,TObject 有 Equals 方法,可以方便地进行相等比较,通过重写此方法,可以将相等代码保留(封装)在类定义中。
  • 非常感谢您的帮助!我试图做的是你最后的命令行,但由于某种原因它说我无法构建它,因为:E2129 无法分配给只读属性。这是代码: var currentposition:integer;开始当前位置:=Lvproxy.CurrentListView.TopItem.Index; RefreshListView(LVProxy.CurrentListView); LVProxy.CurrentListView.TopItem.Index := 当前位置;我可以看到它获得了正确的位置和所有内容,但是由于只读属性,我不能使用该值并插入 currentlistview,无论如何要解决这个问题?
  • Joe,您的代码正在尝试设置恰好位于视口顶部的任何项目的索引。设置对象的索引(如果允许)将在列表中移动项目,而不是滚动视口。要滚动 TListView 的视口,请使用其 Scroll 方法。或致电MakeVisibleTListItem
  • 我该怎么做?很抱歉问,但我现在只是第一次学习德尔福。到目前为止,我很高兴您的回答!
  • 好的,我已经使用 makevisible 再次显示它,但它实际上在图形列表的底部显示了选定的对象。那么刷新时有没有办法在列表底部获取对象的索引?而不是我现在得到的顶部? (我使用 listview.topitem.index)
【解决方案2】:

所以我想在我得到的帮助下,我回答了我自己的问题。 我所做的是编写了一些获取列表视图的 x 和 y 位置的内容,然后在使用 clearlist 进行刷新后,我使用滚动功能返回到相同的功能。我的程序看起来像这样。

procedure Refresh(Sender: TObject);
var
  horzpos:integer;
  vertpos:integer;
begin
    horzpos:=ListView1.ViewOrigin.X;
    vertpos:=ListView1.ViewOrigin.Y;
    RefreshListView(ListView1); //A function that refreshes the list and clears it
    ListView1.Scroll(horzpos, vertpos);
 end;

也许我应该早点说它是一个列表视图类型,并且我想在“clearlist”之后再次回到相同的位置。

感谢大家的帮助,这个社区太棒了!

【讨论】:

    猜你喜欢
    • 2019-08-07
    • 1970-01-01
    • 2018-09-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-06-17
    相关资源
    最近更新 更多