Solved

Faster Dynamic Creation of multiple TShape Components??

Posted on 2003-11-22
8
394 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
How to run any project with ease

Manage projects of all sizes how you want. Great for personal to-do lists, project milestones, team priorities and launch plans.
- Combine task lists, docs, spreadsheets, and chat in one
- View and edit from mobile/offline
- Cut down on emails

 
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

Top 6 Sources for Identifying Threat Actor TTPs

Understanding your enemy is essential. These six sources will help you identify the most popular threat actor tactics, techniques, and procedures (TTPs).

Join & Write a Comment

Objective: - This article will help user in how to convert their numeric value become words. How to use 1. You can copy this code in your Unit as function 2. than you can perform your function by type this code The Code   (CODE) The Im…
In this tutorial I will show you how to use the Windows Speech API in Delphi. I will only cover basic functions such as text to speech and controlling the speed of the speech. SAPI Installation First you need to install the SAPI type library, th…
Sending a Secure fax is easy with eFax Corporate (http://www.enterprise.efax.com). First, Just open a new email message.  In the To field, type your recipient's fax number @efaxsend.com. You can even send a secure international fax — just include t…
Polish reports in Access so they look terrific. Take yourself to another level. Equations, Back Color, Alternate Back Color. Write easy VBA Code. Tighten space to use less pages. Launch report from a menu, considering criteria only when it is filled…

743 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

12 Experts available now in Live!

Get 1:1 Help Now