HOME - - / - - / - -
LAZARUS/ DELPHI COURSE INDEX
- - / - - / - -
TUTORIALS INDEX
- - / - - / - -
Other material for programmers
Lazarus and Delphi Course: First lesson with graphics
Page URL: Graph1.htm
This page is information rich, and a has search button at the bottom of the page.
Please don't dismiss it because it isn't full of graphics, scripts, cookies, etc!
You will probably find the text easier to read if you make your browser window much narrower than usual. You may also want to change your browser's zoom level, to enlarge the text. Opera (at least) lets you change zoom level easily. The text will adapt nicely to the settings you decide give the best results for your needs!
The lines of sample Lazarus/ Delphi code in these pages will not "wrap". I.e., if a line is too long to show in the width you have set your browser too, parts of the line will be "off the page". Those lines will still copy/paste properly, at least in Opera. Please feel free to send feedback on the choices I've made! (Will you forgive me for not forcing upon you a column of links on the left and a column of ads on the right?)
This is just one exercise in a series of Lazarus / Delphi exercises. You will probably be best served by doing them in sequence... each assumes some prior knowledge. Material © TK Boyd, sheepdogsoftware.co.uk, 4/05-6/20.
You may find typos and rough edges in this. None-the-less, the basic information should be accurate. If something seems wrong, or if you find I've assumed knowledge without explaining it in a pious lesson, please let me know. Please forgive matters of typos, etc. for now. I am not inherently sloppy! The blemishes will be dealt with later.
In this lesson, you make an application to draw pretty patterns. The term "graphics" is stretched for this lesson... the "graphics" here are pretty crude. We'll only be doing the sort of thing you could do with a typewriter, but the lesson uses the pretty patterns as a way to discuss some issues. We will do "proper" graphics in the next graphics lesson. While graphics will be crude, the typewriter analogy is a bit too severe: We will have animated graphics by the time we finish.
-- You should learn how to...
--- Put text in a memo
--- Make pretty patterns on the screen
You should learn about....
--- Object hierarchy notation
--- Using loops
Pascal: the language behind both Lazarus and Delphi:
--- Repeat... Until
Lazarus/ Delphi component:
--- Memo
This lesson will produce several small applications which draw pretty patterns on the screen. I hope you will be "inspired" to tweak the applications to vary the pattern. One of the great joys and opportunities in programming is the chance to be creative. Make sure you can do the things described in the lesson, but also explore the "I wonder if I can..." ideas which I hope you will have. Look for some, if they don't come by themselves!
Most of the applications in this lesson are unusual in that they do not require any input from a user. You will work on the code in the unit, and then run the application, and the result of your coding will appear. This is not unknown... consider a screensaver, for example. (But don't think you're going to create one, yet! You will certainly be able to create some pretty graphics by the end of this, but you won't be ready to deal with "hooking" it into the heart of Windows. However, there's nothing to stop you the fruits of this lesson as a pretty thing to cover other things on your screen when you are away from your desk... it is just the automatic starting and stopping of your "screensaver" which will missing.)
Start a new application. Put a memo on the form. Rename the form graph1f1. Save the unit as graph1u1.pas. Save the project as graph1.dpr
Make the form fill at least 1/3 of the screen vertically and horizontally. Make the memo fill most of the form.
Memos are places where you can put lines of text. Rather like working with email, what you and I call a "line" and what the computer calls a "line" can sometimes differ in frustrating ways. The problems can be tamed, but for now, if you keep your lines short enough that they don't reach the right hand edge of the memo, you can avoid the problems. In my instructions below, I will be quite conservative, and make lines short. Feel free to make them longer. (You'll soon see, I hope, the places where "make them longer" should be possible and fun.)
Double click somewhere on the form not on the memo, and not on the title bar. This should start code for the FormCreate event handler. Make it...
procedure Tgraph1f1.FormCreate(Sender: TObject);
begin
memo1.lines.clear;
memo1.lines.add('Hello World');
end;
Good old "Hello World"!
You should get a window with a "window" in it (the memo), with "Hello World" in it.
Now make the FormCreate handler...
procedure Tgraph1f1.FormCreate(Sender: TObject);
begin
memo1.lines.clear;
memo1.lines.add('*');
memo1.lines.add('* *');
memo1.lines.add('* * *');
memo1.lines.add('* * * *');
memo1.lines.add('* * * * *');
end;
Wow! Hey, seriously... You want hard? I can do hard. If this is easy, you can do it quickly, can't you?
What do you make of...
procedure Tgraph1f1.FormCreate(Sender: TObject);
var iCount:integer;
begin
memo1.lines.clear;
iCount:=1;
repeat
if iCount=1 then memo1.lines.add('*');
if iCount=2 then memo1.lines.add('* *');
if iCount=3 then memo1.lines.add('* * *');
if iCount=4 then memo1.lines.add('* * * *');
if iCount=5 then memo1.lines.add('* * * * *');
iCount:=iCount+1;
until iCount>5
end;//FormCreate
Now that's pretty cool... we're not done yet, but we've gone a way forward from the boring way of doing things!
First consider the repeat and the until. They always come in pairs, as above... you always have an until if you've had a repeat. Until is always followed by something which is either true or false.
Remember that iCount:=iCount+1; isn't as weird as it seems. We're merely saying that the contents of the variable iCount should become what they were before, plus one.
Before we go on, we need to look at a possible problem. what would happen if your code said the following. Don't run it yet.
procedure Tgraph1f1.FormCreate(Sender: TObject);
var iCount:integer;
begin
memo1.lines.clear;
iCount:=1;
repeat
if iCount=1 then memo1.lines.add('*');
if iCount=2 then memo1.lines.add('* *');
if iCount=3 then memo1.lines.add('* * *');
if iCount=4 then memo1.lines.add('* * * *');
if iCount=5 then memo1.lines.add('* * * * *');
iCount:=iCount+1;
until (4=5);
end;//FormCreate
(The only change is that I've put 4=5 after the until. 4 will never equal 5, so the program will try to do the loop for ever.)
What happens after you click Run is, apparently, nothing. The computer just sits there. You don't even get an empty window. If you waited long enough, you might get a "not responding" message from Windows, but you might not even get that.
---------------
A long time before 6/20, in Delphi... (see below for "in Lazarus, 6/20")
Happily, one little thing has happened since when you clicked Run...
In the Speedbar, the right-pointing green arrow has gone gray, and the two vertical bars next to it have gone yellow. They are the "pause" button. If you run the application (try it in a moment), clicking on the pause button gets you out of the endless loop that you accidentally created. After you have...
1) gone into something with an endless loop,
2) come out of it with the pause button,
3) modified your code, and
4) clicked Run again...
.... you will be asked: "Source has been modified. Rebuild?" You want to say yes. When you clicked the vertical yellow bars, you only paused the application. Delphi is asking, "Do you want to go back to running the thing that was running, picking up from where you paused it, or do you want to rebuild the .exe file and run the new version?" (For those readers coming to this with some programming experience: It is not a good idea in Windows to put a program into a loop that will not be completed quite soon. Certainly, you don't want to create "Wait until key is pressed" type loops.)
-----------------
June 2020, in Lazarus 2.0.0... (see above for "in Windows, long before 6/20")
Happily, one little thing has happened since when you clicked Run...
In the Lazarus ribbon ("File/ Edit/ Search, etc) Speed bar, the right-pointing green arrow has gone gray, and the red square two places along to the right has gone red. That's the "stop" button. If you run the application (try it in a moment), clicking on the stop button gets you out of the endless loop that you accidentally created. After you have...
1) gone into something with an endless loop,
2) come out of it with the stop button,
3) modified your code, and
4) clicked Run again...
.... you may be asked: "Source has been modified. Rebuild?" You would want to say yes. If you click the vertical yellow bars, you only pause the application. Lazarus is asking, "Do you want to go back to running the thing that was running, picking up from where you paused it, or do you want to rebuild the .exe file and run the new version?" (By the way: It is not a good idea in Windows to put a program into a loop that will not be completed very quickly. If you do, be sure to put an application.processmessages command inside the loop. Certainly, you don't want to create "Wait until key is pressed" type loops.)
(That ends the part of this with two versions of the story.)
Just for a moment, we're going to "wreck" our "pretty graphic". Rewrite the code to make it....
procedure Tgraph1f1.FormCreate(Sender: TObject);
var iCount:integer;
begin
memo1.lines.clear;
iCount:=1;
repeat
memo1.lines.add('* * * * * * * * * *');
iCount:=iCount+1;
until iCount>9
end;//FormCreate
Make sure you see why that works. Notice the indenting I've used in the source code. The indenting makes it easy to see where the repeat loop begins (with the word "repeat") and ends (with the word "until".)
Now change the code again... Try to think what will happen when you click Run before you click Run! You're not doing anything new, really, you're just nesting one loop inside another... with dramatic results...
procedure Tgraph1f1.FormCreate(Sender: TObject);
var iCount, iCount2:integer;
sTmp:string;
begin
memo1.lines.clear;
iCount:=1;
repeat
sTmp:='';
iCount2:=0;
repeat
sTmp:=sTmp+'* ';
iCount2:=iCount2+1;
until iCount2=iCount;
memo1.lines.add(sTmp);
iCount:=iCount+1;
until iCount>25
end;//FormCreate
Do you need help to understand why that does what it does? Where?
Does sTmp:=sTmp+'* '; look strange? We're not adding in the arithmetical sense, we're just making sTmp become what it was previously, with '* ' tacked on to the end.
Why is there an iCount and an iCount2, but no iCount1? You could have an iCount1. I tend not to put it on the first variable in a bunch with similar names, but leave it out so that there is no confusion between a "1-less" iCount, and an iCount1..
Important
I'm now going to write some things a beginner is very unlikely to fully take on board immediately... but they are crucial to your future as a programmer. I hope you realize that anyone needs to work with Lazarus/ Delphi for a while before the big picture really sinks in. It will take a while for your comprehension to mature. Don't be downhearted if you don't write the next great video game overnight!
Lazarus/ Delphi is an object oriented language, as you should have noticed from your reading, even if what that means hasn't come to you yet. What that means is a little harder to get to grips with.
In the application we've just finished, there are two lines which you could type easily enough, but what did they actually mean? I refer to:
memo1.lines.clear;
and
memo1.lines.add(sTmp);
I suggest that you approach things like this as follows....
Take the first one. It is saying "The object memo1 has a lines thingie, and the lines thingie has a clear thingie." (Excuse my use of "thingie" for the moment. I'm trying to help- really!)
Don't try to get to complicated, yet with what an "object" is. If you trip over something left on a sidewalk, you might say, "Who left that object there?!" For now, the general usage of the word is fine. What's magic about the objects in object oriented programming is the things that go with them. The lines thingie that memo1 has is where the text you put in the memo lives. The lines thingie is an example of a property. We can say "The lines property of memo1 currently has two strings of text in it."
I have to work backwards for a moment.
The memo1 object became part of your application when you clicked on the relevant button of the component palette and then clicked on the application's form. The IDE didn't just add the graphical representation of the memo to the form. It also added things to the unit's code. In particular, it added...
memo1: TMemo;
This is very like a variable declaration. It says that within this application, there's going to be an object called, for the moment, memo1. (If you change the object's name, which you can do with the Object Inspector, the IDE takes care of other changes that are needed for you.)
It further says that the object... memo1... will be of the type "TMemo". You remember seeing "type" before? We have data types- string, integer, single, etc. Well, we also have object types. Memo1 is an instance of the type "TMemo". As such it has the properties of all TMemo type objects.
Wait! I'll make it easier for you! (As someone once sang). Imagine with me that Lassie is the best dog that ever there was. Lassie is an object. Lassie is an instance of the "object type" "dog". She has all the "properties" associated with dogs: Legs: 4, Gender: male or female. Size: (within certain limits), etc. Lassie herself was, of course, female. Some dogs are, others are male. However, with respect to legs, dogs generally share the same value in that property. ("Lassie" may have been female. But all the dogs who played the part were males. The things you learn in my tutorials!)
The beauty of object types is that you know quite a lot about something just from knowing what type of object it is.
One thing that makes knowing about objects easy is that they can be built up from units. Take dear Lassie, for instance. She had four legs. How much did you need to learn about dogs' legs if you happened to know a cat before you met your first dog?
The number of legs a dog has is one of the properties of any instance of the "dog" type.
Properties
Lazarus/ Delphi components are the same. All objects have properties. TMemo-type objects have many properties. The one we're using so far is the lines property. Once you know how that behaves in a TMemo object, you'll mostly know how it behaves in other object types. Many objects, of many types, have a "lines" property.
A moment ago, I said you'd already know a bit about dogs if you'd never seen one, but had previously known about cats.
This is because they are both vertebrates
There are differences between cats and dogs, but there are also similarities...because they are both vertebrates. There are similar "families", in a "tree", in objects.
As you become familiar with more object types and the properties and methods of those types, be on the lookout for these similarities.
Be cheered by the fact that after you know a bit about one object type, you have made a start already towards understanding other object types.
Methods
One of the things we used in our application was....
memo1.lines.clear;
Clear is an example of a method. Lines was a property; clear is a method. Objects usually have properties and methods... but, you'll be pleased to hear, that's about all they have. (I won't for now tell you how many of them some objects have!)
memo1.lines.clear;
The "clear" in the above is really the clear that goes with "lines" properties. The fact that this lines is part of a memo isn't (very) important. If you know how the Lines "clear" method works with a TMemo object, you'll know most of what there is to know about how it works for other classes with a "lines" property.
(Almost?) every class of object has a "name" property. You've used the name property extensively, but I doubt you thought very much about it.
It is intuitive. Good. But don't let that blind you to things that are going on. For instance, you know that you can't have a space in an object's name. That is a rule about the name property in general. It doesn't matter if you are talking about the name of a button, of a label, of a form. (Each is an example of a type of object.)
So: To recap something we said before, but in more mature terms:
memo1.lines.add(sTmp);
... says "The object memo1 has a lines property, and the lines property has a clear method."
The difference between properties and methods? About what I hope you would think by now. Properties tell you about the object. Methods are things that can be done with or by or to the object.
As it happens, every TMemo object has a "hide" method, and a "visible" property.
Either of the following would make our instance of the TMemo type disappear from view:
memo1.hide; // Made invisible with method
memo1.visible:=false; // Made invisible by changing value of property
By the way: Not all properties can be altered, but the interesting ones often are.
"Add" is a method of "lines". (A property is also an object, by the way.) Add is a little different from "clear" in that it isn't sufficient on its own. Any time you use the "add" property, you have to supply the thing to be added. That "thing" is called the argument of "add", or its parameter.
Reminder: not so important as what I've been saying, but just to be sure I "planted the seed". Think back to our friend Lassie. She was an instance of the object type (also called "class") "Dog". Dogs are all vertebrates. Vertebrates are all animals. In Delphi there is a similar scheme of inheritance, an object hierarchy. Happily, it isn't too important to you yet, but I hope you'll be intrigued by what it may mean!
You may have gone into "brain seized up" mode. Please make a note to come back to this later. It took me far longer to write it than it has for you to read it, and I didn't do it for me.
Furthermore, I've been programming in Lazarus/ Delphi for more than 20 years. Even now, as I wrote that, I know my grasp of these fundamental issues was growing as I thought about them yet again.
It is far too easy to become overly focused on details, and to lose sight of the big picture which should be guiding us.
Event handlers
I know I just said that I know you are tired. But hang in there just a little longer, and you will "know everything"! Well, "everything" there is to Lazarus/ Delphi anyway.
When you click on a button, stuff happens, if you have put the "stuff" in an event handler.
(Something happens, even if you haven't built an event handler... but usually nothing very noticeable! For every possible event, there are certain default behaviors "built in".)
Event handlers are "just" another property of the object. Albeit a rather odd sort of "property".
Their names usually begin with "On", but that's just a convention. All of my pupils name all of their buttons with "bu" at the start of the name, and next they use a capital (upper case) letter in the name. You could call a button "x23yz". When you get to adding event handler properties to objects, you could call one of them "x23yz". But people don't. They call them OnThis or OnThat, etc.
When you double-click on the representation of one of the objects of your applications, the representation on the form designer, Lazarus/ Delphi adds the shell of a new procedure to the sourcecode. What you put there happens when the event of the object happens, i.e. when you click on the button.
Before long, you will be creating you own procedures, from scratch. Things like the button-click event handlers are, "beneath the skin" fancier than your "basic" procedures will be. You don't need to worry about the differences, I'm glad to say. The IDE takes care of that messy stuff in the background.
The event handlers are really cool. Again- don't worry about the details. Be grateful that Lazarus/ Delphi hides the complexity from you. Makes things simple! (Well, simple compared to other ways of "playing" in a multi-tasking, event-driven world!)
Site Map
What's New
Search
Ad from page's editor: Yes.. I do enjoy compiling these things for you... I hope they are helpful. However.. they don't pay my bills!!! If you find this stuff useful, (and you run an MS-DOS or Windows 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 Sheepdog Software freeware, shareware page.
Link to Tutorials main page
Link to Lazarus/ Delphi Course index
To email this page's editor, Tom Boyd....
Editor's email address. Suggestions welcomed! Please cite "graph1.htm".
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...
One final suggestion: Be sure you know all you need to about spyware.
. . . . . P a g e . . . E n d s . . . . .