HOME  →  Lazarus Tutorials TOC     Other material for programmers

Graphics

Introduction to drawing with Lazarus

file:lt1NGraphics.htm


This page has good information, and a search button at the bottom of the page
Please don't dismiss it because it isn't full of graphics, scripts, cookies, etc!

This page is "browser friendly". Make your browser window as wide as you want it. The text will flow nicely for you. It is easier to read in a narrow window. With most browsers, pressing plus, minus or zero while the control key (ctrl) is held down will change the texts size. (Enlarge, reduce, restore to default, respectively.) (This is more fully explained, and there's another tip, at my Power Browsing page.)




Introduction to Graphics- Lazarus version

(With Delphi equivalent also shown)

Drawing is easy in Lazarus (and Delphi)... once you have a surface to draw on. This tutorial will show you how to create that surface.

I'm going to start with stripped down "do it" instructions which will give you a shell, an app with a (nearly) blank page for doing graphics on.

Further down the page, I explain the basics of using graphics with Lazarus or Delphi.

Quick path to empty shell for graphics work...

Open a new application, save it in the usual way.

If you are unsure about something in the guide, had a look at the complete listing of the finished code which appears at the bottom of this webpage.

Put an "image" control on the form. It's final position and size will be adjusted by code in the FormCreate handler, so don't be too fussy about where you place it.

Put the following in the interface section just below the word "private"...

    Bitmap:TBitmap;
    iImageLeft, iImageTop, iImageWidth, iImageHeight:integer;

(You can't, alas, just copy the code wholesale.

Put the following in the OnCreate event handler...

iImageLeft:=50;
iImageTop:=10;
iImageWidth:=200;
iImageHeight:=100;

Image1.left:=iImageLeft;
Image1.top:=iImageTop;
Image1.width:=iImageWidth;
Image1.height:=iImageHeight;

(*Next, assign bitmap to the image...
This had benefits in Delphi... I think it
was to do with getting what you see on
the screen to survive re-sizings, etc.

Some examples of Lazarus graphics on the web
take a different approach... they simply put
a bitmap directly on the main form. They don't
bother with the image... but they also
over-ride the built in "Paint" handler to do
it. I haven't found problems with my "simpler" approach, at least not under Delphi, and this
little Lazarus "demo" program works.

For the following to work, you'll need a user
defined object called "Bitmap", of type Bitmap
(See full sourcecode, below) *)

Bitmap:=TBitmap.create;//Create a bitmap object
Bitmap.width:=iImageWidth;//Assign dimensions
Bitmap.height:=iImageHeight;

//In Delphi, bitmap background is white to begin with. Black in Lazarus
Bitmap.canvas.pen.color:=clWhite;//1 of 2 lines not needed in Delphi...
Bitmap.canvas.Rectangle(0,0,iImageWidth,iImageHeight);//2 of 2 not needed, Delphi

Image1.Picture.Graphic:=Bitmap; //Assign the bitmap to the image component

That's the general purpose shell created.

The following also go in the OnCreate event handler, just to demostrate a few Lazarus/ Delphi drawing tools. You don't, of course, need these lines in your program for the drawing surface to be present and correct.

//That's our drawing surface "prepared".
//Now do some "tricks" with what we have, and learn
//  where "the edges" of the drawable area are...

//From top left, across top
Image1.Picture.Bitmap.canvas.pen.color:=clGreen;
Image1.Picture.Bitmap.canvas.moveto(0,0);
Image1.Picture.Bitmap.canvas.lineto(150,0);

//From top left, along left edge
Image1.Picture.Bitmap.canvas.pen.color:=clRed;
Image1.Picture.Bitmap.canvas.moveto(0,0);
Image1.Picture.Bitmap.canvas.lineto(0,60);

//From bottom right, up right hand edge
//n.b. the "-1" s
Image1.Picture.Bitmap.canvas.pen.color:=clBlack;
Image1.Picture.Bitmap.canvas.moveto(iImageWidth-1,iImageHeight-1);
Image1.Picture.Bitmap.canvas.lineto(iImageWidth-1,40);

//From bottom right, left along bottom edge
//n.b. the "-1" s
Image1.Picture.Bitmap.canvas.pen.color:=clLime;
Image1.Picture.Bitmap.canvas.moveto(iImageWidth-1,iImageHeight-1);
Image1.Picture.Bitmap.canvas.lineto(50,iImageHeight-1);

//Make an individual pixel black...
//Look closely at the screen when you loop for
//  this... the pixel may be very small
Image1.Picture.Bitmap.canvas.pixels[10,20] := clBlack;

//Text on a graphic...
//    A variety of "pen" properties can be set
//    before calling...
Image1.Picture.Bitmap.canvas.textout(10,30,'Hello');

That's it! Save what you have. Compile and run it. You should see some lines.

And a very small black dot, near the upper left of the drawing area. And some text saying "Hello".


The above "explained"...

Once you have the "shell" app above, if you allow for the fact that the native coordinates run from 0,0 at the upper left, you can use the following. There are various properties you can set beforehand such as the color your "ink" will be, how wide lines will be, what typeface will be used, etc, etc.

But here are the basics, to get you started...

... and that's just for starters.

(If you don't like working from 0,0 at upper left, you can simply create a small function to calculate the coordinate the software needs from the system you want to use.)

The demo in this tutorial will display a window with a TImage component on it, and draw some lines just inside the edges of the image, put a dot on the image, and put "Hello" on it.



Fishing for sympathy...

Will I never learn? About four hours ago, I was working on something in Delphi. I thought to myself, "I ought to post the essence of that in my Lazarus tutorial pages."(And since I wrote that, about three more hours have gone into just the "trivial" parts of wrapping this up... creating the files to download, updating indices, smoothing rough edges.)

It should have been simple. This page. It was going to be just a simple untested listing showing the core of what follows. I didn't think it needed much explanation.

The core is....

1) Fill the following user defined variables (See full sourcecode, below. Specifically, the "type... private..." block.) The canvas you are going to draw on, in this implementation, has to stay the same size all through the program's execution, but you can re-size the window to smaller than the canvas, and still have what you've drawn "there" when you scroll or make the window larger again.

iImageLeft:=50;
iImageTop:=10;
iImageWidth:=200;
iImageHeight:=100;

2) Execute the following once. I do it in the OnCreate handler for the form...

Image1.left:=iImageLeft;
Image1.top:=iImageTop;
Image1.width:=iImageWidth;
Image1.height:=iImageHeight;

(*Next, assign bitmap to the image...
This had benefits in Delphi... I think it
was to do with getting what you see on
the screen to survive re-sizings, etc.

Some examples of Lazarus graphics on the web
take a different approach... they simply put
a bitmap directly on the main form. They don't
bother with the image... but they also
over-ride the built in "Paint" handler to do
it. I haven't found problems with my "simpler" approach, at least not under Delphi, and this
little Lazarus "demo" program works.

For the following to work, you'll need a user
defined object called "Bitmap", of type Bitmap
(See full sourcecode, below) *)

Bitmap:=TBitmap.create;//Create a bitmap object
Bitmap.width:=iImageWidth;//Assign dimensions
Bitmap.height:=iImageHeight;

//In Delphi, bitmap background is white to begin with. Black in Lazarus
Bitmap.canvas.pen.color:=clWhite;//1 of 2 lines not needed in Delphi...
Bitmap.canvas.Rectangle(0,0,iImageWidth,iImageHeight);//2 of 2 not needed, Delphi

Image1.Picture.Graphic:=Bitmap; //Assign the bitmap to the image component

Once you have your bitmap on your image component, here are some of the drawing "tricks" available to you. the examples also show you where "the edges" are.

You CAN do any of the following as soon as you've done the above. You can do them in the OnCreate handler for the form, for instance. But you can also do them at any later time in the program's execution, so, for instance, new dots, lines, text, etc can appear (or disappear: You erase by "drawing" in white the thing you want gone) in response to user input, readings from sensors, etc.

//From top left, across top
Image1.Picture.Bitmap.canvas.pen.color:=clGreen;
Image1.Picture.Bitmap.canvas.moveto(0,0);
Image1.Picture.Bitmap.canvas.lineto(150,0);

//From top left, along left edge
Image1.Picture.Bitmap.canvas.pen.color:=clRed;
Image1.Picture.Bitmap.canvas.moveto(0,0);
Image1.Picture.Bitmap.canvas.lineto(0,60);

//From bottom right, up right hand edge
//n.b. the "-1" s
Image1.Picture.Bitmap.canvas.pen.color:=clBlack;
Image1.Picture.Bitmap.canvas.moveto(iImageWidth-1,iImageHeight-1);
Image1.Picture.Bitmap.canvas.lineto(iImageWidth-1,40);

//From bottom right, left along bottom edge
//n.b. the "-1" s
Image1.Picture.Bitmap.canvas.pen.color:=clLime;
Image1.Picture.Bitmap.canvas.moveto(iImageWidth-1,iImageHeight-1);
Image1.Picture.Bitmap.canvas.lineto(50,iImageHeight-1);

//Make an individual pixel black...
//Look closely at the screen when you loop for
//  this... the pixel may be very small
Image1.Picture.Bitmap.canvas.pixels[10,20] := clBlack;

//Text on a graphic...
//    A variety of "pen" properties can be set
//    before calling...
Image1.Picture.Bitmap.canvas.textout(10,30,'Hello')

And that should have been that. Ha!

Then I weakened, and thought "I'd better just check it really works.

There followed about three hours of confusion. It stemmed mostly from the fact that Lazarus initializes the background of the drawing area with black, whereas Delphi initializes it white. What I wanted to do was probably "working", but I didn't notice it working against the black.

So then I chased off, tried various things.

In the end, I think the Lazarus version (below) and the Delphi version (bottom of page) only differ in that the Lazarus version has the two lines in it to initialize the drawing "page" as white, not black. But at this point, WELL out of time, I'm just listing both WORKING programs as they are...

The following "just works". I put a TImage component called Image1 on the form, apart from creating what you see below. Some of it was started for me by Lazarus, for instance the OnCreate handler's skeleton. (Created via the Object Inspector.)

A zip file containing the sourcecode and an .exe of LDNgraphics1 is available for download. It is 3721kb. The equivalent... nearly identical... Delphi zip was only 161kb. Sigh. But Delphi isn't multi-platform.

unit LDNgraphics1u1;

(*Ver 27 Dec 13, 11:06, with extra comment added
 To go with...
 https://sheepdogguides.com/lut/lt1Graphics.htm
*)

{$mode objfpc}{$H+}

interface

uses
  Classes, SysUtils, FileUtil, Forms, Controls, Graphics, Dialogs, ExtCtrls,
  StdCtrls;

type
  { TForm1 }
    TForm1 = class(TForm)
    Image1: TImage;
    procedure FormCreate(Sender: TObject);
  private
    Bitmap:TBitmap;
    iImageLeft, iImageTop, iImageWidth, iImageHeight:integer;
    { private declarations }
  public
    { public declarations }
  end;

var
  Form1: TForm1;

implementation

{$R *.lfm}

{ TForm1 }

procedure TForm1.FormCreate(Sender: TObject);
begin
iImageLeft:=50;
iImageTop:=10;
iImageWidth:=200;
iImageHeight:=100;

Image1.left:=iImageLeft;
Image1.top:=iImageTop;
Image1.width:=iImageWidth;
Image1.height:=iImageHeight;

(*Next, assign bitmap to the image...
This had benefits in Delphi... I think it
was to do with getting what you see on
the screen to survive re-sizings, etc.

Some examples of Lazarus graphics on the web
take a different approach... they simply put a bitmap
directly on the main form. They don't bother
with the image... but they also over-ride the
built in "Paint" handler to do it. I haven't
found problems with my "simpler" approach, at
least not under Delphi, and this little
Lazarus "demo" program works.*)

Bitmap:=TBitmap.create;//Create a bitmap object
Bitmap.width:=iImageWidth;//Assign dimensions
Bitmap.height:=iImageHeight;

//In Delphi, bitmap background is white to begin with. Black in Lazarus
Bitmap.canvas.pen.color:=clWhite;//1 of 2 lines not needed in Delphi...
Bitmap.canvas.Rectangle(0,0,iImageWidth,iImageHeight);//2 of 2 not needed, Delphi

Image1.Picture.Graphic:=Bitmap; //Assign the bitmap to the image component

//That's our drawing surface "prepared".
//Now do some "tricks" with what we have, and learn
//  where "the edges" of the drawable area are...

//From top left, across top
Image1.Picture.Bitmap.canvas.pen.color:=clGreen;
Image1.Picture.Bitmap.canvas.moveto(0,0);
Image1.Picture.Bitmap.canvas.lineto(150,0);

//From top left, along left edge
Image1.Picture.Bitmap.canvas.pen.color:=clRed;
Image1.Picture.Bitmap.canvas.moveto(0,0);
Image1.Picture.Bitmap.canvas.lineto(0,60);

//From bottom right, up right hand edge
//n.b. the "-1" s
Image1.Picture.Bitmap.canvas.pen.color:=clBlack;
Image1.Picture.Bitmap.canvas.moveto(iImageWidth-1,iImageHeight-1);
Image1.Picture.Bitmap.canvas.lineto(iImageWidth-1,40);

//From bottom right, left along bottom edge
//n.b. the "-1" s
Image1.Picture.Bitmap.canvas.pen.color:=clLime;
Image1.Picture.Bitmap.canvas.moveto(iImageWidth-1,iImageHeight-1);
Image1.Picture.Bitmap.canvas.lineto(50,iImageHeight-1);

//Make an individual pixel black...
//Look closely at the screen when you loop for
//  this... the pixel may be very small
Image1.Picture.Bitmap.canvas.pixels[10,20] := clBlack;

//Text on a graphic...
//    A variety of "pen" properties can be set
//    before calling...
Image1.Picture.Bitmap.canvas.textout(10,30,'Hello');
end;

end.



Delphi version

The following "just works" in DELPHI. I put a TImage component called Image1 on the form, apart from creating what you see below. Some of it was started for me in the usual way by Delphi, for instance the OnCreate handler's skeleton. (Created via the Object Inspector.)

A zip file containing the sourcecode and an .exe of LDNgraphics1Delphi is available for download. It is 161kb. The equivalent... nearly identical, in design and function... Lazarus zip was a staggering 3,721kb. Sigh. But Lazarus is multi-platform.

I run the program, and I see a white rectangle within the form, with some lines along parts of edges, a dot, and "Hello".

As I said, I think this differs from "the Lazarus version" only in lacking the two lines during the creation of the image-with-bitmap which fill it with white initially.

unit LDNgraphics1DelphiU1;
//Name derived from fact that this is
// Delphi equivalent of LDNgraphics1, which
// was written to go with...

//https://sheepdogguides.com/lut/lt1Graphics.htm

(*Quick check of grasp of basic graphics, ver 28 Dec 13..
with tweak here not in downloadable version. Remmed*)

interface

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

type
  TLDNgraphics1DelphiF1 = class(TForm)
    Image1: TImage;
    procedure FormCreate(Sender: TObject);
  private
    Bitmap:TBitmap;
    iImageLeft, iImageTop, iImageWidth, iImageHeight:integer;
   { Private declarations }
  public
    { Public declarations }
  end;

var
  LDNgraphics1DelphiF1: TLDNgraphics1DelphiF1;

implementation

{$R *.DFM}

procedure TLDNgraphics1DelphiF1.FormCreate(Sender: TObject);
begin
iImageLeft:=20;
iImageTop:=10;
iImageWidth:=500;
iImageHeight:=300;

Image1.left:=iImageLeft;
Image1.top:=iImageTop;
Image1.width:=iImageWidth;
Image1.height:=iImageHeight;

Bitmap:=TBitmap.create;//Create a bitmap object
Bitmap.width:=iImageWidth;//Assign dimensions
Bitmap.height:=iImageHeight;

(*Next, assign bitmap to the image...
This had benefits in Delphi... I think it
was to do with getting what you see on
the screen to survive re-sizings, etc.

Some examples of Lazarus graphics on the web
take a different approach... they simply put a bitmap
directly on the main form. They don't bother
with the image... but they also over-ride the
built in "Paint" handler to do it. I haven't
found problems with my "simpler" approach, at
least not under Delphi, and this little
Lazarus "demo" program works.*)

Image1.Picture.Graphic:=Bitmap;//Assign the bitmap to the image component

//Start: Bit not in downloadable version...

//In Delphi, bitmap background is white to begin with. //Background defaults black in Lazarus. If you want
//  to change the background color to, say, red, you
//  can do it with...

Bitmap.canvas.pen.color:=clRed;
Bitmap.canvas.brush.color:=clRed;//makes for FILLED rectangle
Bitmap.canvas.Rectangle(0,0,iImageWidth,iImageHeight);

//... end of bit not in downloadable version.

//That's our drawing surface "prepared".
//Now do some "tricks" with what we have, and learn
//  where "the edges" of the drawable area are...

//From top left, across top
Image1.Picture.Bitmap.canvas.pen.color:=clGreen;
Image1.Picture.Bitmap.canvas.moveto(0,0);
Image1.Picture.Bitmap.canvas.lineto(300,0);

//From top left, along left edge
Image1.Picture.Bitmap.canvas.pen.color:=clRed;
Image1.Picture.Bitmap.canvas.moveto(0,0);
Image1.Picture.Bitmap.canvas.lineto(0,100);

//From bottom right, up right hand edge
//n.b. the "-1" s
Image1.Picture.Bitmap.canvas.pen.color:=clBlack;
Image1.Picture.Bitmap.canvas.moveto(iImageWidth-1,iImageHeight-1);
Image1.Picture.Bitmap.canvas.lineto(iImageWidth-1,50);

//From bottom right, left along bottom edge
//n.b. the "-1" s
Image1.Picture.Bitmap.canvas.pen.color:=clLime;
Image1.Picture.Bitmap.canvas.moveto(iImageWidth-1,iImageHeight-1);
Image1.Picture.Bitmap.canvas.lineto(50,iImageHeight-1);

//Making an individual pixel black...
Image1.Picture.Bitmap.canvas.pixels[10,20] := clBlack;

//Text on a graphic...
//    A variety of "pen" properties can be set
//    before calling...
Image1.Picture.Bitmap.canvas.textout(10,30,'Hello');

end;//FormCreate

end.

Remember: The code above is DELPHI code. The Lazarus version is at the top of the page.




More?

If this didn't quite get the ideas across for you, maybe try my older tutorial introducing drawing graphics in Delphi? Lazarus graphics seem to match what Delphi did, at least in the basics.





Search across all my sites with the Google search...

Custom Search

Or search just SheepdogGuides.com with the Freefind tool...

   Search this site or the web          powered by FreeFind
  Site search Web search
Site Map    What's New    Search

This search merely looks for the words you enter. It won't answer "Where can I download InpOut32?"


If you visit 1&1's site from here, it helps me. They host my website, and I wouldn't put this link up for them if I wasn't happy with their service. They offer things for the beginner and the corporation.www.1and1.com icon

Ad from page's editor: Yes.. I do enjoy compiling these things for you. I hope they are helpful. However... this doesn't pay my bills!!! Sheepdog Software (tm) is supposed to help do that, so if you found this stuff useful, (and you run a Windows or MS-DOS PC) please visit my freeware and shareware page, download something, and circulate it for me? Links on your page to this page would also be appreciated!
Click here to visit editor's freeware, shareware page.

Link to Lazarus Tutorials main page
How to contact the editor of this page, Tom Boyd


Valid HTML 4.01 Transitional Page has been tested for compliance with INDUSTRY (not MS-only) standards, using the free, publicly accessible validator at validator.w3.org. Mostly passes.

AND passes... Valid CSS!


If this page causes a script to run, why? Because of things like Google panels, and the code for the search button. Why do I mention scripts? Be sure you know all you need to about spyware.

....... P a g e . . . E n d s .....