我在运行时生成面板。我在表单上有一个面板,然后我在里面有一个scrollBox alClient。在scrollBox里面我动态添加了面板。它们都属于Scrollbox,我生成后将它们对齐到底部。所以他们一个接一个地出现。
我使用的代码如下:
Procedure TMain.AdaugaElement(numar:integer; tip:string);
var
pan:TPanel;
semn:TShape;
pos:TPoint;
lab:TLabel;
myimg:TImage;
bmpsep, dest:TBitmap;
begin
pan:=TPanel.Create(self);
pan.Parent:=ScrollBox1;
pan.Align:=alBottom;
pan.Height:=50;
pan.Name:='Layeru'+IntToStr(numar);
pan.Caption:='Elementul '+IntToStr(numar);
pan.Font.Color:=$00004F4F;
pan.Font.Quality:=fqAntialiased;
pan.Color:=$0080FFFF;
pan.OnMouseDown:=layerRowMouseDown;
pan.ParentColor:=false;
pan.ParentBackground:=false;
pan.Color:=clWhite;
Pos:= pan.ClientOrigin;
vt.AppendRecord([vt.RecordCount+1,Pan.name,numar,numar,0 ,0, 20,20,800,600,pan.Caption,tip]);
lab:=TLabel.Create(self);
lab.Parent:=pan;
lab.Left:=54;
lab.Top:=16;
lab.Font.Size:=10;
lab.Font.Color:=clBlack;
lab.Font.Style:=[];
lab.Font.Quality:=fqAntialiased;
lab.Caption:=IntToStr(numar);
Randomize;
lab.Name:='Layernumber'+IntToStr(numar);
semn:=TShape.Create(self);
semn.Parent:=pan;
semn.Left:=3;
semn.Top:=3;
semn.Height:=44;
semn.Width:=44;
semn.Pen.Color:=$00009D9D;
semn.Brush.Color:=clWhite;
myimg:=TImage.Create(self);
myimg.Width:=42;
myimg.Height:=42;
myimg.Left:=4;
myimg.Top:=4;
myImg.Visible:=true;
myimg.Proportional:=true;
myimg.Stretch:=true;
myImg.Parent:=pan;
SelectLayerPan(numar);
end;
SelectLayerPan
程序会模拟表格中的选定行,因此当我添加新面板时,它会显示为“已选择”' (它'取消选择'所有面板然后选择'新面板)
vt
是VirtualTable
,我在其中输入有关生成的面板的信息
所以我添加这样的面板:
AdaugaElement(1,'type1');
AdaugaElement(2,'type1');
AdaugaElement(3,'type1');
AdaugaElement(4,'type1');
接下来,我想使用鼠标在各自之间移动面板。所以最初我添加了:
- panel5
- panel4
- panel3
- panel2
- panel1
(按此顺序)
然后使用鼠标拖动panel1并将其放在panel4和panel5之间。因此它们将显示为:
- panel5
- **panel1**
- panel4
- panel3
- panel2
(按此顺序)
此拖放操作在layerRowMouseDown中完成。
但是,因为在virtualTable中我有关于面板的信息(按原始顺序),所以
record1: panel1 pos:1
record2: panel2 pos:2
record3: panel3 pos:3
record4: panel4 pos:4
record5: panel5 pos:5
我必须识别移动的面板记录并更新它以便它将反映其新位置,因此VirtualTable必须如下所示:
record1: panel1 pos:4
record2: panel2 pos:1
record3: panel3 pos:2
record4: panel4 pos:3
record5: panel5 pos:5
我该怎么做?
我的意思是,当我放下面板时,如何检测面板的最终位置?或者,我如何获得容器中的面板顺序(ScrollBox1)?
到目前为止,我尝试使用FindVCLWindow(pos)
使用面板的起始位置和倍数来识别面板(及其在scrollBox中的顺序),但是当有更多面板时,它们不再可见直接(没有滚动),它显然停止正常工作。
所以这不是解决方案
答案 0 :(得分:0)
Top
中面板的TScrollBox
属性似乎是面板顺序的唯一可靠指标。要查找面板的顺序,您可以将面板临时分配到列表,然后在Top属性上对该列表进行排序。现在,您将在列表中按照它们在滚动框中显示的顺序排列它们。
以下只是使用临时列表进行排序的示例。您需要对其进行修改以适合您的目的。
procedure TForm6.UpdateRecords;
var
Comparer: IComparer<TMyPanel>;
i: integer;
s: string;
begin
Comparer := TDelegatedComparer<TMyPanel>.Create(
function (const A, B: TMyPanel):integer
begin
Result := A.Top - B.Top;
end);
TempPanelList := TMyPanelList.Create(Comparer);
try
for i := 0 to ScrollBox1.ControlCount-1 do
TempPanelList.Add(TMyPanel(ScrollBox1.Controls[i]));
TempPanelList.Sort;
for i := 0 to TempPanelList.Count-1 do
begin
// replace this with your own code, something like in next snippet
s := s + ', ' + inttostr(TempPanelList.items[i].Tag);
Label1.Caption := s;
//
end;
finally
TempPanelList.Free;
end;
end;
然后,要在列表中的面板和vt
中的相应记录之间获取引用,您可以在创建面板时使用tag
属性。您似乎将参数numar
传递给AdaugaElement过程,因此假设这可以作为vt
的索引,您可以将此numar
分配给pan.Tag
。
最后要更新pos
中的vt
字段,您可以在循环中指定面板的新位置,在此循环中将TempPanelList中TPanel的索引指定为{{1}中的pos记录。 注意!我不知道使用vt
VirtualTable
但是你的设置在许多帐户上看起来都非常脆弱,而上述内容并没有帮助。您正在分配TMain实例(表单?)作为所有这些TPanel,TShapes,TLabels和TImages的所有者。当用户添加和删除图层时,它会变得非常混乱。我想创建一个复合类TLayerItem来保存与一个层和LayerManager类相关的所有内容来管理TLayerItems。
答案 1 :(得分:-2)
这似乎是一种效率低下的解决方案。还有,为什么重新发明轮子?
您所描述的内容与工具栏的工作方式非常相似,只是它是垂直布局而不是水平布局。我会查看一些工具栏的来源,看看你是否可以使用已经设计好的东西来做你想做的事情。如果不出意外,您将获得一些好主意如何实施您尝试做的事情。
或者,我会考虑在滚动框内使用TFlowPanel,您可以将面板放在流动面板上,而不是直接放在滚动框上。
编辑:我向有人低估了这一点道歉,但我们不允许指出异地内容,而且我不打算在这里发布几个工具栏组件的所有代码。