我需要根据一些规则重新排序 TObjectList。我怎样才能做到这一点?
所以我动态地将面板添加到 ScrollBox。当我添加它们时,我还会按照它们在运行时添加的顺序将它们添加到 ObjectList 中,以备将来使用。然后我可以通过拖放重新组织滚动框中的面板。我希望 ObjectList 镜像在运行时通过拖放设置的相同顺序。
这是我的代码:
var
MainForm: TMainForm;
PanelList,PanelListTMP:TObjectList;
implementation
...
procedure TMainForm.FormCreate(Sender: TObject);
begin
PanelList:=TObjectList.Create;
PanelListTMP:=TObjectList.Create;
end;
procedure TMainForm.Button1Click(Sender: TObject);
begin
AddPanel('0');
AddPanel('1');
AddPanel('2');
AddPanel('3');
AddPanel('4');
end;
procedure TMainForm.Addpanel(what:string);
var
pan:TPanel;
bv:TShape;
begin
pan:=TPanel.Create(self);
pan.Parent:=TheContainer;
pan.Height:=50;
pan.BevelOuter:=bvNone;
pan.BorderStyle:=bsNone;
pan.Ctl3D:=false;
pan.Name:='LayerPan'+what;
pan.Caption:=what;
pan.Align:=alBottom;
pan.OnMouseDown:=panMouseDown;
end;
procedure TMainForm.panMouseDown(Sender: TObject; Button: TMouseButton;Shift: TShiftState; X, Y: Integer);
var
i:integer;
idu:String;
panui:TPanel;
begin
panui:=Sender as TPanel;
panui.ParentColor:=false;
panui.BringToFront;
// DRAG DROP STUFF
ReleaseCapture;
panui.Perform(wm_nclbuttondown,HTCAPTION,0);
for i := 0 to MainForm.ComponentCount - 1 do
begin
if MainForm.Components[i] is TWinControl then
if TWinControl(MainForm.Components[i]) is TPanel then
if (TWinControl(MainForm.Components[i]) as TPanel).Parent=MainForm.TheContainer then
begin
(TWinControl(MainForm.Components[i]) as TPanel).Align:=alBottom;
end;
end;
TheContainer.ScrollInView(panui);
ReOrderPanels;
end;
Procedure TMainForm.ReOrderPanels;
begin
end;
在 ReOrderPanels 过程中我应该做什么?我正在考虑将 ScrollBox 的面板从下到上馈入新的 TObjectList (PanelListTMP),清除 PanelList 并从 PanelListTMP 重新添加它们,但是当我这样做时,出现错误:访问冲突和 EInvalidPointer - 无效的指针操作
所以这就是我的想法:
procedure TMainForm.ReOrderPanels;
var
ctrl:TControl;
pos:TPoint;
pan:TPanel;
bad:boolean;
ord,i:integer;
begin
memo2.Lines.Add('*** new order START');
panelListTMP.Clear;
// scroll top
TheContainer.VertScrollBar.Position := 0;
// scroll down
TheContainer.VertScrollBar.Position := TheContainer.VertScrollBar.Range;
// get panel
Pos:=TheContainer.ClientOrigin;
Pos.Y:=Pos.Y+TheContainer.Height-5;
ctrl := FindVCLWindow(pos) ;
if ctrl is TPanel then
if TPanel(ctrl).Parent = TheContainer then
begin
pan:=(ctrl as TPanel);
panelListTMP.Add(pan);
end;
ord:=1;
bad:=false;
repeat
repeat
Pos.Y:=pos.Y-1;
until (FindVCLWindow(pos) is TPanel)and(FindVCLWindow(pos)<>pan);
if (FindVCLWindow(pos) is TPanel)and(FindVCLWindow(pos).Name<>'LayerPan') then
begin
pan:=FindVCLWindow(pos) as TPanel;
containeru.VertScrollBar.Position := 0;
containeru.ScrollInView(pan);
ord:=ord+1;
panelListTMP.Add(pan);
end
else
bad:=true;
until bad=true;
// and now I do the swap between the ObjectLists...
panelList.Clear;
for i:=0 to PanelListTMP.Count-1 do
begin
(PanelListTMP.Items[i] as TPanel).Parent:=containeru;
panelList.Add(PanelListTMP.Items[i]);
end;
end;
所以我假设因为 ObjectList 正在存储指向实际对象的指针,那么当我清除初始 ObjectList 时,实际对象被释放,所以第二个 ObjectList 包含一个不再可行的指针列表......但是那怎么能我实现了我想要的?
所以在 ButtonClick 上,我得到一个 ObjectList,其中包含按以下顺序排列的面板:
PanelList[0] - Panel0
PanelList[1] - Panel1
PanelList[2] - Panel2
PanelList[3] - Panel3
PanelList[4] - Panel4
在 ScrollBox 内拖放面板后,我可以得到这样的订单(在 ScrollBox 中)
Panel3
panel1
Panel4
Panel2
Panel0
但是在ObjectList中,顺序和之前一样……
同样,我希望能够根据滚动框中的面板顺序对 ObjectList 进行排序。在重新排序过程中,我实际上按所需顺序获得了所有面板。我只需要在我的 ObjectList 中以相同的顺序排列它们。
有没有其他方法可以做到这一点?其他与我创建一个新类,该类将在 TPanel 旁边保存一个索引并在 ObjectList 中使用它来维护顺序?