Loading images into TImage, via array

9k views Asked by At

I'm very new to delphi, doing a project for my A level. When I run my code the images just don't show, I've looked everywhere and my teacher can't help me. Can anyone tell me what I'm missing?

    const
       Animal : array[0..6] of string =                    ('Bears','Dogs','Cats','Chickens','Horses','Cows','Monkeys');
    ImagePaths : array [0..6] of string
      = ('img0.JPG', 'img1.JPG', 'img2.JPG', 'img3.JPG', 'img4.JPG', 'img5.JPG',
        'img6.JPG');

  var i:integer;
  Images : array [0..11] of TImage;

procedure LoadImages;
  var
  k,l:integer;
  begin
  Randomize;
  k:=Random(11);
  for l:= 0 to k do
  begin
    Images[l] := TImage.Create(nil);
    Images[l].Picture.LoadFromFile(ImagePaths[i])
  end

end;

procedure TForm4.FormCreate(Sender: TObject);
begin
randomize;
i:=random(6);
QuestionLbl.Caption:=Format('How many %s are there?',[Animal[i]]);
LoadImages;
end;

The idea is that a random number of images of the same randomly selected animal is displayed for a child to then count and input, if that helps. Much appreciate any help.

edit.

as this is only a prototype I have copied it all to a new application and this is all the code I didn't include:

unit Unit1;

interface

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

type
  TForm1 = class(TForm)
    QuestionLbl: TLabel;
    procedure FormCreate(Sender: TObject);
      private
    { Private declarations }
  public
    { Public declarations }
  end;

The same error is occurring and I'm afraid I'm too ignorant to follow what I'm sure were very clear instructions.

4

There are 4 answers

2
Fabricio Araujo On BEST ANSWER

Why you just don't put your TImages on the form, and just LoadFromFile the ones you want to show ? Appear to me that would be easier.

But: what you trying to accomplish? From the code, I can imagine you were trying to show a number of images to people count them and answer the question...

So, if you add (and position) the 11 empty(no image) TImages in the form, you can do:

// Any trouble in copying your FormCreate header, David? ;-)
procedure TMyForm.FormCreate(Sender: TObject);
begin
  Images[0] := Image_N1; // First TImage
  Images[1] := Image_N2;
  Images[2] := Image_N3;
  // Do that until the 12 slots are filled
  // As a exercise for Danny Robinson( the OP ), you can do that in a for..do using 
  // the Form.Components array property to automate it instead of 
  // doing one-at-a-line
end;

procedure ClearImages;
var I: Integer;
begin
  for I = Low(Images) to High(Images) do
  begin
    Images.Picture.Graphic := Nil;
  end;
end;



procedure LoadImages;
var
  k,l:integer;
begin
  ClearImages;
  Randomize;
  k:=Random(11);
  for l:= 0 to k do
  begin
    Images[l].Picture.LoadFromFile(ImagePaths[i])
  end;

end;

If you still need to create the TImages on the fly, just create the 12 TImages once on FormCreate (as in David's answer) and keep calling the LoadImages.

EDIT:

Some ideas, since you are learning.
Creating visual controls on-the-fly is a very boring(in my opinion, of course) task that involves:

  • Creating the object, obviously
  • Assigning it to a parent control (forms doesn't need this pass)
  • Sizing it accordingly to your visual planning
  • Positioning it in the place of the parent control you want it to be
  • Set it's anchors, for it to reposition and/or resize when the parent control is resized (if needed)
  • Only after all this, make it do what you want it to do (in this case, showing images).

Almost all those steps David Heffernan's answer show the code for it. But, unless you really need a dynamic layout, doing all those on design-time is more practical ;-)

8
David Heffernan On

What appears to be missing is that you need to tell the image which control is its parent so that it can appear on screen. Do that like this:

Images[l].Parent := TheForm;

Obviously your form variable will have a different name, but I'm sure you know what it's called.

When you do this you will find that they all end up on top of each other. Assign to the Top and Left properties to position then. Finally you will likely want to set the Height and Width properties of the images to match the dimensions of the images, Images[l].Picture.Height and Images[l].Picture.Width.


I can't imagine why your code produces an access violation but it's presumably unrelated to the question you asked. The following code proves that what I say above is correct:

procedure TMyForm.FormCreate(Sender: TObject);
var
  Image: TImage;
begin
  Image := TImage.Create(Self);
  Image.Parent := Self;
  Image.Picture.LoadFromFile('C:\desktop\image.jpg');
  Image.Top := 0;
  Image.Left := 0;
  Image.Height := Image.Picture.Height;
  Image.Width := Image.Picture.Width;
end;

Without your full code I cannot debug your AV.

0
Nickname On

TImage component must to be painted on the screen, for do so make a 1pixel panel as the parent to load the graphics. like in a loading screen so the images can be used as default TImage procedures.

2
Remy Lebeau On

You need to set the Parent property of each TImage in order to see them onscreen. You can't use the global Form pointer variable, though, because it has not been assigned yet when the OnCreate event is triggered. So pass in the form's Self pointer as a parameter of LoadImages() instead.

You have another bug - you declared a 12-element TImage array but declared a 7-element String array for the image paths. The way you are using Random(), if it generates a value above 6, you will go out of bounds of the String array.

Try this instead:

const
  ...
  ImagePaths : array [0..6] of string = ('img0.JPG', 'img1.JPG', 'img2.JPG', 'img3.JPG', 'img4.JPG', 'img5.JPG', 'img6.JPG');

var
  i: integer;
  Images : array [0..6] of TImage;

procedure LoadImages(AParent: TWinControl);
var
  i, k: integer;
begin
  Randomize;
  k := Random(7);
  for i := 0 to k do
  begin
    Images[i] := TImage.Create(nil);
    Images[I].Parent := AParent;
    // set other properties, like Left/Top...
    Images[l].Picture.LoadFromFile(ImagePaths[i]);
  end;
end;

procedure TForm4.FormCreate(Sender: TObject);
begin
  ...
  LoadImages(Self);
end;