HOME - - / - - / - - DELPHI COURSE INDEX - - / - - / - - TUTORIALS INDEX - - / - - / - - Other material for programmers

Delphi Course: First lesson with graphics

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 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?)

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 previous 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 heirarchy notation
--- Using loops

Delphi language:
--- Repeat... Until

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, andnot on the title bar. This should start code for the form's OnCreate 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 OnCreate 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;
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 iCount>5
end;
(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 forever.)

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. Happily, one little thing has happened. In the Speedbar, the right-pointing green arrow has gone grey, 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.)
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>5
end;
Make sure you see why that works. Notice the indenting I've used which 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>5
end;
Where do you need help? 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 that you are very unlikely to fully take on board immediately... but they are crucial to your future as a programmer. Although, I hope, the following is "clear", you will need to work with Delphi for a while before the significance of it all begins to sink in. It will take a while for your comprehension to mature. I suppose if this were a course in marriage guidance, someplace early on I'd be saying "It is important to listen to the clients." Well, yes... but just how you do that is the trick!

Delphi is an object oriented language, as you cannot have escaped noticing. 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 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 thing that memo1 has is where the text you put in the memo lives. The lines thing 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. Delphi 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, Delphi will change the relevant line of your code, too.)

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.

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 be on friendly terms with a cat before you met your first dog?

Delphi components are the same. 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 another type of object.

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 wojn';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.

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 expect you would think. 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 intersting 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 arguement of "add", or its parameter.

One last thing... not so important as what I've already said, but just to "plant a 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 heirarchy. Happily, it isn't too important to you yet, but I hope you'll be intrigued by what it may mean!




Click here if you're feeling kind! (Promotes my site via "Top100Borland")
   Search this site or the web        powered by FreeFind
 
  Site search Web search
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.. this doesn'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 (tm) freeware, shareware page.

Link to Tutorials main page Link to Delphi Course index
Here is how you can contact this page's author, Tom Boyd.


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


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 .....