Faster Dynamic Creation of multiple TShape Components??

Hi,

I am writing an application that requires a 50x60 matrix of TShapes (i.e. 3000 TShapes!) to be displayed on the screen at the same time.  I am currently doing this dynamically, with the following code:

========================================================
unit Unit1;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls, ExtCtrls;

type
  TForm1 = class(TForm)
    Button1: TButton;
    procedure Button1Click(Sender: TObject);
    procedure FormCreate(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
  end;

var
  Form1: TForm1;
  Ar: Array[0..50, 0..60] of TShape;

implementation

{$R *.dfm}

procedure TForm1.Button1Click(Sender: TObject);
var
  i, j: integer;
begin

  for i:=0 to 50 do
    begin
      for j:=0 to 60 do
        begin
          Ar[i][j] := TShape.Create(form1);
          ar[i][j].Parent := form1;
          ar[i][j].Top := 20+(j+(j*10));
          Ar[i][j].Left :=20+( i+(i*10));
          Ar[i][j].Width := 10;
          Ar[i][j].Height := 10;
        end;
    end;

end;

procedure TForm1.FormCreate(Sender: TObject);
begin
FORM1.DoubleBuffered := TRUE;
end;

end.
=========================================================

The problem is it takes an awful long time to display them all.  I was just wondered wheather there is a quicker way to do this so they appear almost instantly??

Thanks.

engdmorrAsked:
Who is Participating?
I wear a lot of hats...

"The solutions and answers provided on Experts Exchange have been extremely helpful to me over the last few years. I wear a lot of hats - Developer, Database Administrator, Help Desk, etc., so I know a lot of things but not a lot about one thing. Experts Exchange gives me answers from people who do know a lot about one thing, in a easy to use platform." -Todd S.

FeralCTOCommented:
Here are a couple of ideas:

* Maybe you could multi-thread and create the TShapes at startup? Put them in a TObjectList. That way they'd be sitting in memory ready to use when the user clicked the button. If you're not too familiar with threads, Indy (www.indyproject.org) has a thread component which makes multi-threading really easy.

* DoubleBuffered uses a lot of memory. I'm assuming you have that enabled to reduce flicker during painting. I don't have a specific suggestion on this one, but you might want to play with WHEN you enable that property.

* I'm guessing there's a lot of painting going on the way your code is right now. I suspect that's where the performance hit is coming from. You could try setting the TShape's properties for top, left, height and width BEFORE you set the parent. In addition, you could place a panel on the form and have that be the parent for the shapes. Set the Panel to Invisible while you're getting the shapes onto it and positioned. Once they're all on it, then make the panel visible. FYI, TPanel has the DoubleBuffered property, too. So you could still achieve the flicker free repainting.

Good luck. If you solve this satisfactorily, it would be cool if you'd post your solution for the rest of us to see.


0
FeralCTOCommented:
Alright, I couldn't help but play with your code! :-)  I tried some of my suggestions and it DEFINITELY helped. Here's the modified code:

procedure TForm1.Button1Click(Sender: TObject);
var
  i, j: integer;
begin

  FORM1.DoubleBuffered := False;   // turn DoubleBuffered off while we get all the shapes in place
  for i:=0 to 50 do
    begin
      for j:=0 to 60 do
        begin
          Ar[i][j] := TShape.Create(form1);
//          ar[i][j].Parent := form1;    
          ar[i][j].Top := 20+(j+(j*10));
          Ar[i][j].Left :=20+( i+(i*10));
          Ar[i][j].Width := 10;
          Ar[i][j].Height := 10;
          ar[i][j].Parent := form1;    // I moved this to here from above
        end;
    end;
  FORM1.DoubleBuffered := TRUE;

end;
0
engdmorrAuthor Commented:
Thanks for the comments, havent tried any yet though!  I was thinking of maybe creating my own TShape component based on a simple rectangle.  I have just drawn 3000 rectangles to the screen in a fraction of the time a TShape takes, I'm assuming the object instantiation for a TShape takes a lot of resources.  Will get back to you all with the results.  Will try the suggestions 1st though, thanks once again :)
0
Cloud Class® Course: C++ 11 Fundamentals

This course will introduce you to C++ 11 and teach you about syntax fundamentals.

FeralCTOCommented:
If you're willing to put a little (maybe a lot) of work into it, you can do all of the drawing yourself using TCanvas. You could draw on an offscreen graphic and then copy the image to something onscreen (form, canvas, TImage, etc). That would eliminate flicker similar to the way DoubleBuffered does.
0
andrewjbCommented:
I'd agree - draw them yourself in one master control if possible. 3000 components are likely to cause resource problems on a Win9x machine, if that's an issue...
0
DeerBearCommented:
Hi,

I think the problem here is not the code, but what you want to do, so I ask you:
what do you really want to do? <g>.

Please explain and I'm sure we'll get very far.

Cheers,

Andrew
0
engdmorrAuthor Commented:
Just to clarify why I need so many shapes, I am designing kind of a wierd packet analyser.. A cross between the GUI you get with Win9x Defrag and a network sniffer.

The packet sniffing is not a problem as I already designed my own NDIS drivers ages ago.  Basically, each of the squares represents the individual packet: The square will be coloured green if OK, red if collision occured, Brown border for TCP, Orange for UDP etc.. etc...  When you click on the square in question the data for the packet will be displayed, headers, data etc..

There is 50 frames of data per second being squirted out onto the network and I want to analyse a full minutes worth at once.. Hence the need for so many shapes!!

It would be nice to have this full minutes worth of data, but perhaps not essential.  I may end up just displaying a 50 x 20 array to display 20 seconds of data instead.

Hope this clarifies the need for so many shapes.

By the way, this is not a commercial product I am developing but my own nerdy idea so I will probably post it somewhere in the future if I manage to pull it off :)
0
DeerBearCommented:
Hi,

Consider this scenario:

Type
   
   TPacketData = class( TObject )
    // Here you define the packet data retrieved from NDIS driver
   end;

   TPacketEvent = procedure( Sender : TObject;Data : TPacketData );
   TPacketRepresentation = class( TObject )
   public
       procedure Draw( Canvas : TCanvas );virtual;abstract;
       function Intersects( P : TPoint ) : Boolean;virtual;abstract;
       property Data : TPacketData;
   end;

   TPacketRectangle = class( TPacketRepresentation )
   public
      procedure Draw( Canvas : TCanvas );override;
      function Intersects( P : TPoint ) : Boolean;override;
      property Left : Integer;
      property Top : Integer;
      property Right : Integer;
      property Bottom : Integer;
   end;
 
   TPacketList = class( TPacketRepresentation )
   private
      FPackets : TObjectList;
    public
       procedure Draw( Canvas : TCanvas );override;
       function Intersects( P : TPoint ) : Boolean;override;
       
       property Count : Integer read GetCount;
       property Packets[ Index : Integer ] : TPacketRepresentation read GetPacket;
   end;
   
   TPacketsView = class( TCustomControl )
   private
     PacketList : TPacketList;
   protected
      procedure Paint;override;
      procedure DblClick;override;
   public
      constructor Create( AOwner : TComponent );override;
      destructor Destroy;override;
     
       property OnPacketData : TPacketEvent;
   end;

This is how, imho, things should be done... do you like it?

Implementing it should not be difficult.

HTH,

Andrew
0

Experts Exchange Solution brought to you by

Your issues matter to us.

Facing a tech roadblock? Get the help and guidance you need from experienced professionals who care. Ask your question anytime, anywhere, with no hassle.

Start your 7-day free trial
It's more than this solution.Get answers and train to solve all your tech problems - anytime, anywhere.Try it for free Edge Out The Competitionfor your dream job with proven skills and certifications.Get started today Stand Outas the employee with proven skills.Start learning today for free Move Your Career Forwardwith certification training in the latest technologies.Start your trial today
Delphi

From novice to tech pro — start learning today.

Question has a verified solution.

Are you are experiencing a similar issue? Get a personalized answer when you ask a related question.

Have a better answer? Share it in a comment.