2011-07-31 61 views
2

我试图排序标签的值。我有很多带有整数值的标签。标签被称为Label1,Label2,[...],Im通过FindComponent访问。我在存储在数组中的整数值排序时没有问题,但问题是,排序后,我不知道哪个标签具有什么价值。我的目标是喜欢根据它们的值对这些标签进行排序,这样我就可以像使用按值排序的标签一样获得数组。林停留在这一点:( 如:德尔菲标签值排序

Label1.Caption := 10; 
Label2.Caption := 4; 
Label3.Caption := 7; 

for i := 1 to 3 
do some_array[i] := StrToInt(TLabel(FindComponent('Label' + IntToStr(i))).Caption); 

sortarray(some_array); 

现在,我已经整理排列,但是我缺乏这将也是在相应的地方商店的标签数量可有人点我了

回答

1
某种程序?

而不是创建一个整数数组的,创造的TLabel控件数组。这一次,你可以顺便为整数数组相同的排序。事实上,给定一个MyLabel: TLabel,你可以很容易地获得相关的整数StrToInt(MyLabel.Caption)

另外,FindComponent方法不是非常有效。我会做

const 
    ALLOC_BY = 100; 
    MAGIC_TAG = 871226; 
var 
    i: Integer; 
    ActualLength: integer; 
    FLabels: array of TLabel; 
begin 
    SetLength(FLabels, ALLOC_BY); 
    ActualLength := 0; 
    for i := 0 to ControlCount - 1 do 
    if Controls[i] is TLabel then 
     with TLabel(Controls[i]) do 
     if Tag = MAGIC_TAG then 
     begin 
      if ActualLength = length(FLabels) then 
      SetLength(FLabels, length(FLabels) + ALLOC_BY); 
      FLabels[ActualLength] := Controls[i]; 
      inc(ActualLength); 
     end; 
    SetLength(FLabels, ActualLength); 

    SortArray(FLabels) // with respect to the StrToInt(CurLabel.Caption) of each 
        // CurLabel: TLabel. 

当然,你可以跳过块分配,如果你知道标签的数量提前。

确保要包含在阵列中的每个标签的Tag设置为MAGIC_TAG

另一种选择是创建一个数组

FLabelDataArray: array of TLabelData; 

type 
    TLabelData = record 
    Control: TLabel; 
    Value: integer; 
    end; 

其中

FLabelDataArray[i].Value := StrToInt(FLabelDataArray[i].Control.Caption); 

被计算一次。

+2

我是唯一一个认为排序标签是无稽之谈的人吗?标签不应该用于存储,IMO。一个应该使用真正的存储(如数组或TList )并对其进行排序。 –

+0

@Rudy:我完全同意。但我被给了这个问题,所以我回答了。我能做的事情不多。 –

+0

看到我的答案。人们可以学习。

0

正如Andreas所说,把标签放入一个动态数组中,而不是对数值进行排序。一旦这种阵列中有他们,对它们进行排序是这样的:

uses 
    Generics.Defaults, Generics.Collections; 

procedure SortLabels(var Labels: array of TLabel); 
var 
    Comparison: TComparison<TLabel>; 
    Comparer: IComparer<TLabel>; 
begin 
    Comparison := function(const Left, Right: TLabel): Integer 
    begin 
     Result := StrToInt(Left.Caption)-StrToInt(Right.Caption); 
    end; 
    Comparer := TDelegatedComparer<TLabel>.Create(Comparison); 
    TArray.Sort<TLabel>(Labels, Comparer); 
end; 
+0

我使用delphi 7;不能找到仿制药:( – Klemik

+0

没有仿制药在d7 –

1

快速正肮脏的解决方案,也能在老德尔福版本,就是用TStringList,其中有一个Sort方法和Objects财产允许您将一个对象与列表中的每个条目相关联。

请注意,列表按字典顺序排序,所以整数在转换为字符串时必须用零填充。

var 
    list: TStringList; 
    i: integer; 
    lab: TLabel; 
begin 
    Label1.Caption := '10'; 
    Label2.Caption := '4'; 
    Label3.Caption := '7'; 

    list := TStringList.Create; 
    try 
    for i := 1 to 3 do begin 
     lab := TLabel(FindComponent('Label' + IntToStr(i))); 
     list.AddObject(Format('%10.10d', [StrToInt(lab.Caption)]), lab); 
    end; 

    list.Sort; 

    for i := 0 to list.Count-1 do 
     Memo1.Lines.Add(list[i] + #9 + TLabel(list.Objects[i]).Name); 
    finally 
    list.Free; 
    end; 
end; 

输出将是:

0000000004 Label2 
0000000007 Label3 
0000000010 Label1 

而且,如果不是list.Sort您使用list.Sorted := true,你会得到list作为奖金二进制搜索(使用list.IndexOflist.Find)。

编辑:作为鲁迪说,可视化组件如TLabel应该只用于显示数据,而不能用于存储和操作它。建议为此使用适当的数据结构,并将程序的逻辑与其用户界面分开。

+0

这对我工作最好;谢谢 – Klemik

+0

@Klemik如果这是最好的答案,那么请考虑接受它。 COM /问题/ 5234 /如何-不接受-的回答工作 –

0

正如其他人所说,我不认为你正在采取正确的方法来完成这项任务。但是,根据您的问题,一个简单的黑客会使用每个标签上的标签属性来存储它的标题值:

Label1.Caption := '10'; 
Label1.Tag:=10; 
Label2.Caption := '4'; 
Label2.Tag:=4; 
Label3.Caption := '7'; 
Label3.Tag := 7; 

然后你就可以与入门“整数数组”匹配找到合适的标签标签的标签属性。

还是那句话:随着鲁迪和其他人评论说,你的方法把这个任务还远远没有希望的,我的解决方案不仅符合你的方法。标签属性本身是德尔福内置的一种黑客技术,它是古代的一种神器,比如'label'和'goTo',真的不应该使用,除非绝望 - 比如当试图重新工作和复古适合古代,写得不好的代码,或者如果你有刺激的东西,你必须快速解决紧急情况。