关于动态生成大量控件对速度的问题,和如何多选动态生成的控件。请高手赐教!(200分)

  • 主题发起人 主题发起人 CrazyCat
  • 开始时间 开始时间
faint,自己画吧,控件不是这么用的。
 
xeen,自己画的我已经完成了,只是想要找个更好的方法,能交给系统做的为什么不交呢?我是这样想的,也许大家的想法有写不太相同!
 
把您的 8000 个 Shape 生成的时间贴出来让大家瞧瞧吧。方便俺们知道什么叫系统做的。
不会是指不动脑子吧?俺的机器上光生成 8000 个 Shape 就用掉 12531 ms ,这个时间
俺大约可以叫一个 1024X768 大小的 TBitmap 产生的位图上下翻转 964 次,而且不会象
生成这 8000 个 Shape 那样独占着 CPU 来完成,也不会象这 8000 个 Shape 那样占用
6 MB 内存。当然,也许彼此的想法实在大不相同,但我可以保证您的机器不会再快于我
上面写出来的时间了。
 
留名,看看大家的讨论,学习ing
 
见鬼,这个时间我把一个 1152X864X16M 色,计 2.8 MB 的位图,上下逐点翻转了 1045 次,
耗去的时间也只是 12547 ms。这些点比您的 Shape 不知道多多少?
 
哈哈,我现在使用的是:
Map.Canvas.Brush.Color:=clWindow;
Map.Canvas.FillRect(Map.Canvas.ClipRect);
Map.Canvas.StretchDraw(Map.BoundsRect,MJpg);

//Map.Canvas.Brush.Color:=ClBlue;
//Map.Canvas.Pen.Color:=ClBlue;
DM.SeatTable.First;
While Not DM.SeatTable.Eof do begin
Map.Canvas.Brush.Color:=StringToColor(Trim(DM.SeatTable.FieldByName('Color').AsString));
Map.Canvas.Pen.Color:=Map.Canvas.Brush.Color;
Map.Canvas.RoundRect(DM.SeatTable.FieldByName('SeatX').AsInteger,
DM.SeatTable.FieldByName('SeatY').AsInteger,
DM.SeatTable.FieldByName('SeatX').AsInteger+DM.SeatTable.FieldByName('Width').AsInteger,
DM.SeatTable.FieldByName('Seaty').AsInteger+DM.SeatTable.FieldByName('Height').AsInteger,
1,1);
DM.SeatTable.Next;
end;
Map为一个IMAGE控件。
鼠标判断:
DM.TempQuery.Close;
DM.TempQuery.SQL.Clear;
DM.TempQuery.SQL.Add('Select * from Seat where (SeatX>='+IntToStr(x)+')and(SeatX<='+IntToStr(X)+'+2)and(SeatY<='+IntToStr(y)+')and(SeatY>='+IntToStr(y)+'-2)');
DM.TempQuery.Open;
if not DM.TempQuery.IsEmpty then begin
//Application.MessageBox('hello','',0);
{Map.Hint:=}
Memo.Lines.Add(DM.TempQuery.FieldByName('Area').AsString+'区'
+DM.TempQuery.FieldByName('Line').AsString+'排'
+DM.TempQuery.FieldByName('Seat').AsString+'座');
end;
只是想要找一种更方便快捷的方式,你也可以试一下我上面说的那种方法,我不是想不动脑子,而是想要找一种更快捷的方法。
原来做的代码程序:
{DM.TempQuery.Close;
DM.TempQuery.SQL.Clear;
DM.TempQuery.SQL.Add('Select Max(Area) from Seat');
DM.TempQuery.Open;
MaxI:=DM.TempQuery.Fields[0].AsInteger+1;

DM.TempQuery.Close;
DM.TempQuery.SQL.Clear;
DM.TempQuery.SQL.Add('Select Max(Line) from Seat');
DM.TempQuery.Open;
MaxJ:=DM.TempQuery.Fields[0].AsInteger+1;

DM.TempQuery.Close;
DM.TempQuery.SQL.Clear;
DM.TempQuery.SQL.Add('Select Max(Seat) from Seat');
DM.TempQuery.Open;
MaxK:=DM.TempQuery.Fields[0].AsInteger+1;

SetLength(ShapeArray,MaxI,MaxJ,MaxK);

SeatPanel.DisableAlign;
DM.SeatTable.First;
While not DM.SeatTable.Eof do begin
ShapeArray[DM.SeatTable.FieldByName('Area').AsInteger][DM.SeatTable.FieldByName('Line').AsInteger][DM.SeatTable.FieldByName('Seat').AsInteger]:=TShape.Create(Self);
With ShapeArray[DM.SeatTable.FieldByName('Area').AsInteger][DM.SeatTable.FieldByName('Line').AsInteger][DM.SeatTable.FieldByName('Seat').AsInteger] do begin
Name:='';
Left:=DM.SeatTable.FieldByName('SeatX').AsInteger;
Top:=DM.SeatTable.FieldByName('SeatY').AsInteger;
Width:=DM.SeatTable.FieldByName('Width').AsInteger;
Height:=DM.SeatTable.FieldByName('Height').AsInteger;
//Brush.Color:=IdentToColor(DM.SeatTable.FieldByName('Color').AsString);
Cursor := crHandPoint;
DragCursor := crDrag;
DragMode := dmAutomatic;
Hint:=DM.SeatTable.FieldByName('Area').AsString+'区'
+DM.SeatTable.FieldByName('Line').AsString+'排'
+DM.SeatTable.FieldByName('Seat').AsString+'座';
OnMouseMove:=ShapeMouseMove;
OnEndDrag:=ShapeEndDrag;
Tag:=DM.SeatTable.FieldByName('SeatID').AsInteger;
Parent:=SeatPanel;
//end;
end;
DM.SeatTable.Next;
Application.ProcessMessages;
end;}
可能大家误解了我的意思了,还有对于多选的,我现在也找到做的方法了,使用API函数
DrawFocusRect(),大家有兴趣可以试一下,还有没更好的办法?
 
我在做的是把一个场馆中的座位图实时的生成出来,有改动的情况下数据库中也相应的改动。支持鼠标拖放,数据格式大家看我上面的代码应该可以了解一二,现在的做法是鼠标移动到特定位置时生成一个SHAPE来完成原来8000个中的一个完成的鼠标拖动。
 
在选中时动态产生 Shape 或者自己专门的控件,是个好思路,有点写程序的味道。
下面的简单做法就可以生成一个场景:
const
HSpace=20;
VSpace=10;
procedure TForm1.DrawScene(SceneWidth,SceneHeight:integer);
var
R,DrawR:TRect;
H,V:integer;
B:TBitmap;
HoriCount:integer;
VertCount:integer;
DrawLeft:integer;
DrawTop:integer;
begin
B:=TBitmap.Create;

DrawR:=Rect(0,0,B.Width,B.Height);
R:=Rect(0,0,B.Width,B.Height);

InflateRect(R,HSpace div 2,VSpace div 2); // 实际应该从真实的表里取得坐标

HoriCount:=SceneWidth div R.Right;
VertCount:=SceneHeight div R.Bottom;

// List:=TList.Create; 本例子不深入写,所以不创建,目的用来储存位置点
for V:=0 to VertCount-1 do
begin
DrawTop:=R.Bottom*V; // 求垂直偏移
B.LoadFromFile(IntToStr(V)+'.bmp'); // 某种颜色或效果的座位示意图(每排)
for H:=0 to HoriCount-1 do
begin
DrawLeft:=R.Right*H; // 求水平偏移
bitblt(Canvas.Handle,DrawLeft,DrawTop, // 画出位置图(真实情况应该画入持久画布里)
DrawR.Right,DrawR.Bottom,B.Canvas.Handle,0,0,SRCCOPY);
// 这里加入位置点的储存,以便于在 Mouse Moving 时使用 ptInRect 确定是哪个矩形
end;
end;
B.Free;
end;

假如发生 Moving ,不需要改变场景图,只在确定 Moved 时才需要重画。
选中,无非就是画一个框框,这时可以直接画在 Shape 上,而假如继承一下 TGraphicControl
可以生成自己的 Shape ,这个自己的 Shape 甚至可以暴露 Canvas 属性,使自己的 Shape
可以贴上效果图、选中框等等效果。
多选,一般的处理比较困难,大都自己继承一个画图控件来支持。

如果我来做,假如这是一个真实的商业化软件,我会生成专门的控件来完成这些工作。以上
完全是个人观点。
 
to 小雨哥:
谢谢你的意见,并给出例子代码,我也想过要通过继承一个控件来生成我的对象,但工程时间很短,只好先用这种方法来做了,等完成后看看有没时间去生成一个,也希望和你多探讨一下这方面的东西,在谈的一个项目中可能需要生成4万个点来表示一个场景,对次速度方面的提高还要再完善的。
To all:
大家还有什么好的提议吗?我找到了一本DELPHI5 API函数开发实例,其中对文字和图像的WINDOWS API介绍的非常全面。大家要是也在做这方面的工作可以去找一下。
其中有很多的API可以帮助我们完成DELPHI IDE 中的很多功能。
 
我靠,8000个shape就是动态生成内存也不行??是作什么?是画地图坐标还是干什么?同意LEEMA的方法用鼠标坐标方法定位(但必须在Directx的画布上!用D3D函数写程序;游戏地图的编写方法才能使程序速度加快。否则你的程序GUI编程方法下运行即使能做出来,用户用你的程序时显示速度也是没人能忍受的。)
 
哦?Directx,我还没研究过,但我现在的速度也不错了,只是遍例数据库时速度慢点,我并不要很复杂的图形,只是简单的,不过这方面提议不错,有空研究一下!
 
TO:gjdemj2000
没这么夸张吧,一般应用根本不用使用 DirectX ,而且 DirectX 也不见得比 GUI 下
直接编码快多少,不相信我可以给您一个不使用 DirectX 、而只使用原生 Delphi IDE 下
直接可以使用的东西写一个比 DirectX 翻转还要快的演示。
已经完成的演示可以看:
http://www.01cn.net/noncgi/attach/2004/05/07/5736-ImgTest.rar
这是一个 TBitmap 效果处理。
http://www.01cn.net/noncgi/attach/2004/05/11/5784-AlpTest.rar
这是一个 TBitmap 双图融合演示
http://www.01cn.net/noncgi/attach/2004/05/13/5833-Moving.rar
这是一个类似 DirectX 的动画演示(含源)
再不然,手里有个刚写的演示,就是上面帖子提到的 TBitmap 快速翻转,测试结果上面已经写了。
 
呵呵 ,小雨哥 高手就是高手 , 敬佩ing..........
 
你是哪儿的朋友,我也在做类似的开发。希望交流,关于二维定位显示相关信息,
相当于GIS吧(当然是简单的)。
scczhxy@sohu.com
 
to 小雨哥:
佩服、佩服。
看来你对图象编程有很深的功力吗!学习中。。。。。。。
 
谁有好东西,或好的思想,大家讨论一下啊!继续。。。。。。。
 
一个场馆可分为不同的区域,如:东区、西区、南区、北区、1区、2区、3区...N区等
这样的话你可以在程序里将不同区的信息显示在不同PageControl页中,这样每一页显示时要动态创建的控件数就少了很多了(每一页只在第一次进入时创建,下次进去时就不用创建了,速度就更快了),如果每一区可以再分成更小的区域的话那就更快了(具体实现方法只能你自个去想了),而操作人员在查找座位时也可以提高效率,因为我们已经帮他分好区域了,如果不分的话在8000个座位中找到某个座位可不是件容易的事,这样可以做的真正的双赢,我的意思你明白吧。
 
这我也想过了,但完成起来不是很理想,看不到整体效果!而且,我使用数据库就是想要动态的改变位置等的不同显示效果。
还有什么好的提议吗?
 
这种要求不太适合用大量的控件实现,自己写个控件是比较好的选择。因为的你的用户的输入方式不太复杂,从TScrollWinControl继承下来,只要处理少数的事件就可以了。
 

Similar threads

S
回复
0
查看
3K
SUNSTONE的Delphi笔记
S
S
回复
0
查看
2K
SUNSTONE的Delphi笔记
S
D
回复
0
查看
2K
DelphiTeacher的专栏
D
后退
顶部