2011-04-26 139 views
0

我想知道如何在创建的列表中获得某个对象的位置。 可以说它就像一个图形列表,您可以点击对象。 让我们说你右键单击一个对象,然后单击“刷新”,我如何获得该对象的位置,以便在整个列表刷新后(由于某种原因刷新清单),我回到同一个位置清单?这是如果列表说1000个对象长,这使得刷新后尝试向下滚动到相同位置是麻烦的。在Delphi中获取列表中对象的位置?

该代码使用Tobject,但我可以做些什么,如 position:= integer(TObject。“pointerinfo ???”); 然后,当程序刷新 就像设置视图的位置像指针 像currentview(指针)或类似的东西?

实际上它不一定是同一个对象,但列表的相同“视图”会更好。

在此先感谢

+1

你在找'TListItem.Index'吗?你失去了我的位置:=整数(TObject。“pointerinfo ????”);' – 2011-04-26 12:53:33

+2

什么是“图形列表”和“对象”?您尝试使用哪些课程?你能展示代码示例吗? – Andrew 2011-04-26 13:11:36

回答

1

所以我觉得在我得到的帮助下,我回答了我自己的问题。 我所做的就是编写一些需要使用listview的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; 

也许我应该在前面说过这是一个listview类型,我希望在“清单”之后再次回到相同的位置。

感谢所有的帮助,这个社区的岩石!

4

如果耳目一新会再次给你相同的名单,并以相同的顺序,那就不必发现关于对象的任何东西。只需存储列表控件的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; 

在所有这些情况下,你应该认识到该对象在列表中的位置是不实际的对象的属性。相反,它是列表的属性,这就是为什么列表在所有代码中扮演比对象更重要的角色的原因。实际上并没有任何“指针信息”可以从对象中获取,因为对象通常不知道它甚至不在列表中,所以它肯定不会知道它相对于列表中的所有其他项的位置。

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

List.TopIndex := ObjectPosition; 

最后,如果你不真正关心当前对象所有,但只是要恢复当前滚动位置,那么这更容易:

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

TStrings类实际上有一个'IndexOfObject'方法,它可以更快地找到对象(只要对象地址没有改变)。在较新版本的Delphi中,TObject具有Equals方法,可以方便地进行等式比较,通过重写此方法,等式代码可以保存(封装)在类定义中。 – mjn 2011-04-26 14:54:09

+0

非常感谢您的帮助! 我试图做的是你的最后一个命令行,但由于某种原因它说我无法构建它,因为:E2129无法分配给只读属性。 这是代码: var currentposition:integer; 开始 当前位置:= Lvproxy.CurrentListView.TopItem.Index; RefreshListView(LVProxy.CurrentListView); LVProxy.CurrentListView.TopItem.Index:= Currentposition; 我可以看到它得到正确的位置和所有,但我不能使用该值并插入当前listview由于只读属性,无论如何解决这个问题? – Joe 2011-04-26 15:08:51

+0

乔,你的代码试图设置哪个项目恰好位于视口顶部的索引。设置对象的索引(如果允许的话)将*移动列表*中的项目,而不是滚动视口。要滚动“TListView”的视口,请使用其“Scroll”方法。或者在'TListItem'上调用'MakeVisible'。 – 2011-04-26 16:06:39