Solved

Faster Dynamic Creation of multiple TShape Components??

Posted on 2003-11-22
8
396 Views
Last Modified: 2010-04-05
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.

0
Comment
Question by:engdmorr
  • 3
  • 2
  • 2
  • +1
8 Comments
 
LVL 1

Expert Comment

by:FeralCTO
ID: 9803350
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
 
LVL 1

Expert Comment

by:FeralCTO
ID: 9803378
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
 

Author Comment

by:engdmorr
ID: 9803477
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
 
LVL 1

Expert Comment

by:FeralCTO
ID: 9804155
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
Is Your Active Directory as Secure as You Think?

More than 75% of all records are compromised because of the loss or theft of a privileged credential. Experts have been exploring Active Directory infrastructure to identify key threats and establish best practices for keeping data safe. Attend this month’s webinar to learn more.

 
LVL 12

Expert Comment

by:andrewjb
ID: 9809854
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
 
LVL 5

Expert Comment

by:DeerBear
ID: 9810111
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
 

Author Comment

by:engdmorr
ID: 9811603
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
 
LVL 5

Accepted Solution

by:
DeerBear earned 125 total points
ID: 9816282
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

Featured Post

Is Your Active Directory as Secure as You Think?

More than 75% of all records are compromised because of the loss or theft of a privileged credential. Experts have been exploring Active Directory infrastructure to identify key threats and establish best practices for keeping data safe. Attend this month’s webinar to learn more.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Suggested Solutions

Title # Comments Views Activity
how to draw animated progressbar in Tvirtualstringtree 5 117
creating manifest for my dll that called from activex 6 99
Magic Software info 18 125
update joined tables 2 31
Have you ever had your Delphi form/application just hanging while waiting for data to load? This is the article to read if you want to learn some things about adding threads for data loading in the background. First, I'll setup a general applica…
Introduction Raise your hands if you were as upset with FireMonkey as I was when I discovered that there was no TListview.  I use TListView in almost all of my applications I've written, and I was not going to compromise by resorting to TStringGrid…
In this video I am going to show you how to back up and restore Office 365 mailboxes using CodeTwo Backup for Office 365. Learn more about the tool used in this video here: http://www.codetwo.com/backup-for-office-365/ (http://www.codetwo.com/ba…
As a trusted technology advisor to your customers you are likely getting the daily question of, ‘should I put this in the cloud?’ As customer demands for cloud services increases, companies will see a shift from traditional buying patterns to new…

920 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

15 Experts available now in Live!

Get 1:1 Help Now