0

OK, I'm trying to create some custom number of TPanel's at runtime on TScrollBox surface like you can see on following image.

enter image description here

To get this I'm using following code and that works fine.

var
  pan: array of TPanel;
  maxp, i, x, y: Integer;

...

maxp := 10;
SetLength(pan, maxp);

for i := 1 to maxp do begin
  // x is correct value; doesn't cause problem
  // y is correct value; doesn't cause problem
  pan[i-1] := TPanel.Create(form1);
  with pan[i-1] do begin
    Width := 100;
    Height := 150;
    Top := x * 151;
    Left := y * 101;
    Parent := ScrollBox1;
    end;
  end;

Now, I have problems to put TImage object in every TPanel with same index (img[0] -> pan[0], img[1] -> pan[1], etc). Look at the following image:

enter image description here

Using same logic, I've tried to create TImage's but w/ no success.

I'm using this code and cant figure out what's wrong. It looks so simple to me, but somehow it doesn't provide expected effect.

var
  pan: array of TPanel;
  img: array of TImage;
  maxp, i, x, y: Integer;

...

maxp := 10;
SetLength(pan, maxp);
SetLength(img, maxp);

for i := 1 to maxp do begin
  // x is correct value; doesn't cause problem
  // y is correct value; doesn't cause problem
  pan[i-1] := TPanel.Create(form1);
  with pan[i-1] do begin
    Width := 100;
    Height := 150;
    Top := x * 151;
    Left := y * 101;
    Parent := ScrollBox1;
    end;
  img[i-1] := TImage.Create(form1);
  with img[i-1] do begin
    Width := 98;
    Left := 1;
    Height := 148;
    Top := 1;
    // in original code next line had img[0]. which caused problem
    Picture.LoadFromFile('some_image_file');
    Parent := pan[i-1];
    end;
  end;

Somehow it places all TImage objects on same place in first TPanel (pan[0]). It's confusing for me because it says Parent := pan[i-1]; but for some reason it always puts TImage in pan[0]. I've tried using breakpoints to see what's going on after every for-loop cycle (added Application.ProcessMessages at the end) and it really creates 10 different images but puts them onto pan[0]. Of course, at the end it shows just last image loaded into pan[0].

My question is how to make one dynamic TImage per dynamic TPanel (with same array indices)?

SOLVED!

Wh1T3h4Ck5
  • 8,399
  • 9
  • 59
  • 79
  • Perhaps nicer to do this with a single call to `SetBounds` – David Heffernan Apr 21 '12 at 21:47
  • @DavidHeffernan - sorry, I've tried using `SetBounds(1, 1, 98, 148);` and `SetBouds(x*151, y*101, 100, 150)` instead of setting individual Width, Height, Left and Top properties but effect is same. – Wh1T3h4Ck5 Apr 21 '12 at 21:53
  • Sure the effect is the same. I didn't mean that is would answer your question. Just that it's cleaner. – David Heffernan Apr 21 '12 at 21:54
  • @DavidHeffernan, sure... that was just quick test to try getting it to work. – Wh1T3h4Ck5 Apr 21 '12 at 21:56
  • Just a quick question... do the `x`and `y` get changed somewhere or do you put all the panels to the same position? –  Apr 21 '12 at 22:15
  • Agree, Tibor. There's no mention in the code of how the x and y values get updated. I would expect a couple of lines setting x to (i-1) mod 5, and y to (i-1) div 5. – bjaastad_e Apr 21 '12 at 22:59
  • @Elling, dude, problem has been solved about 40 minutes ago (look bellow to my answer). Btw, X and Y are used for positioning of TPanels (to get proper row/column) and as you can see from pictures above, TPanels are already on right places. Positions of TImages are relative inside TPanels and X and Y dont affect their positioning. – Wh1T3h4Ck5 Apr 21 '12 at 23:09
  • @Wh1T - For 10 or so maxp it is quite fine, but if this is going to be a kind of an image browser or the like, I'd advise against using a window (panel) per image as it might end up having to create thousands. – Sertac Akyuz Apr 22 '12 at 01:01
  • @Wh1T - Ok, I see. In other words there's some code which is not shown in the above snippet, updating x and y. – bjaastad_e Apr 22 '12 at 06:55
  • 1
    If you want some extra advice, I'd suggest creating a separate component TImagePanel for the thumbnail functionality. It'll give you better code separation, and make it easier to maintain and extend the functionality later on. – bjaastad_e Apr 22 '12 at 07:03
  • Some more advice. When someone finds a typo in your question such that the code in the question does not match the code that you are running, fix the question with an edit. Otherwise you just waste our time by getting us to debug the wrong code. Andreas told you about the Height typo. You said that your code wasn't like that. Then Tibor told you again. And so on. It's really irritating when this happens. – David Heffernan Apr 22 '12 at 07:38
  • @DavidHeffernan - Yes you're right, I forgot to update it after "height" suggestion like I did after previous few comments. Btw, Tibor's comment was about X,Y variables which are not related with positioning dynamic TImage's so it was not necessary to fix or update anything. You can see that panels are showing on right place and coordinates of TImage's are relative to their parent TPanel's so the way I'm getting X and Y is really not related w/ problem. But generally, you're right about correcting code on suggestions. – Wh1T3h4Ck5 Apr 22 '12 at 16:51

3 Answers3

5

And word of advice - get rid of the with blocks. They may seem innocent and simple at first, but in the long run they only serve to write sloppy code that is hard to troubleshoot. Had you been using explicit variable references instead, this problem would never had occurred in the first place.

var
  Panels: array of TPanel;
  Panel: TPanel;
  Images: array of TImage;
  Image: TImage;
  maxp, i, x, y: Integer;

...

maxp := 10;
SetLength(Panels, maxp);
SetLength(Images, maxp);

for i := 1 to maxp do begin
  Panel := TPanel.Create(form1);
  Panels[i-1] := Panel;
  Panel.Parent := ScrollBox1;
  Panel.SetBounds(...);
  Image := TImage.Create(form1);
  Images[i-1] := Image;
  Image.Parent := Panel;
  Image.SetBounds(...);
  Image.Picture.LoadFromFile('some_image_file');
end;
Remy Lebeau
  • 555,201
  • 31
  • 458
  • 770
2

You set Height twice and no Left, so it seems.

with pan[i-1] do begin
  Width := 100;
  Height := 150;
  Top := x * 151;
  Height := y * 101;
  Parent := ScrollBox1;
end;
  • 1
    +1 for your effort. Just found mistake. Nothing's wrong here, another typo. As you can see from pictures above panels are positioned on right places. However, thanks m8. – Wh1T3h4Ck5 Apr 21 '12 at 22:21
1

Ah, I found it... how blind I am really...

To get auto-complete in delphi, i've used img[0] in front of Picture.LoadFromFile(). Then, obviously I forgot to remove it from code, and since hour ago that 'prefix' stayed there making all images load into same img[0]. I was sure there's something wrong with Parent or Pos/Size properties and have been focused on this things not caring so much about this.

I actually had

  with img[i-1] do begin
    Width := 98;
    Left := 1;
    Height := 148;
    Top := 1;
    img[0].Picture.LoadFromFile('some_image_file');
    Parent := pan[i-1];
    end;

But somehow I've removed that img[0] part while posting this question, and haven't seen it as problem in my Delphi code. Obviously, when I was formatting this code, i removed some parts and that made answering my question here impossible :(

Really sorry for bothering you guys, that was my bad.

Wh1T3h4Ck5
  • 8,399
  • 9
  • 59
  • 79
  • 2
    There is nothing wrong with that as far as I am concerned :) Sometimes other people can spot our mistakes more easily than ourselves no matter how banal they are. So there's nothing wrong with posting questions like that on SO. –  Apr 21 '12 at 22:25
  • @Tibor, I understand that, but also been so frustrated because that `Parent := pan[i-1];` line shows image always in `pan[0]` and that kept me focused away of line before. The worst thing, I was kicking my head against the wall for an hour trying to fix something w/ perfectly correct logic. Guess I was so tired to see obvious mistake :( – Wh1T3h4Ck5 Apr 21 '12 at 22:45