Solved

Why does this work on child form but not mainform ?

Posted on 2011-03-12
30
558 Views
Last Modified: 2012-05-11
Hi,

The second line of this procedure loads a picture into a TImage on this child form. The third line should do the same on the parent form, but doesn't. Why, and what is the best fix ? FilePath is a String.

procedure TForm1.FileListBox1Click(Sender: TObject);
begin
  FilePath := FileListBox1.FileName;
  Image1.Picture.LoadFromFile(FilePath);
  MainForm.Image1.Picture.LoadFromFile(FilePath);
end;
0
Comment
Question by:ChLa
  • 10
  • 9
  • 3
  • +3
30 Comments
 
LVL 32

Expert Comment

by:ewangoya
ID: 35117500

That code works well. What version of Delphi are you using?

Second, the fact that you have MainForm referenced in Form1, you have a circular reference. This is not good.
0
 
LVL 9

Expert Comment

by:Mahdi78
ID: 35117780
Add MainForm Unit name to Form1 uses clause
0
 

Author Comment

by:ChLa
ID: 35117943
Form1 is a child to MainForm, I must prefix "MainForm" in it's child or it wouldn't recognize the Timage on the main form. I get no error messages. How is this a circular reference ? Main is already a unit in the Form1 uses clause, and it won't let me add MainForm. Form1 is in the uses clause of the main form. I am using Delphi 2010. When I select a picture in the filelistbox, it displays in the TImage on the child form, Form1. But the TImage on the main form never changes.
0
 
LVL 9

Expert Comment

by:Mahdi78
ID: 35117966
Do you get this problem with bitmap picture?
0
 

Author Comment

by:ChLa
ID: 35118091
So far I have been testing the program only with a folder holding five small .jpg's. I can load a picture into the timage on the main form at design time and it displays, but never changes. I can leave the timage empty at design time and I cannot see  it on the form. And no other image will load. I am assuming that if the code were on the same form it would work as it does in the timage on the child form. But I haven't tried that yet. .As far as I can tell both timages have the same settings.
0
 

Author Comment

by:ChLa
ID: 35118727
Now I am really confused. On the main form I copied this: Image1.Picture.LoadFromFile(FilePath); to a button on-click event. I also made the button display the string in FilePath so I could be sure the string was populated and visible, and that the on-click event happened. I open the child form, select an image, it displays in the timage on the child form, and then close the child form. Then I click the button on the main form. The button shows the correct filename. But no picture is visible. I thought perhaps there was some bad setting in this timage. So I deleted it and added a new one. It still won't display the image, unless I select one at design time. It doesn't make sense.
0
 
LVL 32

Expert Comment

by:ewangoya
ID: 35118929

Where is the variable FilePath declared
0
 
LVL 32

Expert Comment

by:ewangoya
ID: 35118931

Is it possible for you to upload the two units here. The I can debug them properly
0
 
LVL 2

Expert Comment

by:RezaSadigh
ID: 35119414
Hi my friend,
1- Set MainForm.Image1.Stretch:= True (may be it is loaded but on the hidden part of MainForm.Image1)
2- Maybe your Timage needs to be Refreshed. Try this:
      MainForm.Image1.Refresh;
      Application.ProcessMessage;
after MainForm.Image1LoadFfromFile
Best regards;
0
 

Author Comment

by:ChLa
ID: 35121770
FilePath is declared in the global declarations of the child form.
I seem to be experiencing anomalous behavior from Delphi and I am thinking either I have a bad installation of Delphi, or there is a problem with the laptop I am using, or there is some incompatibility between Delphi 2010 and Windows 7.

I am using Delphi 2010 on a Dell Vostro Laptop with windows 7.

I wrote a program that copies every other file from one folder to another. On the vostro I was seeing two anomalies. First, FileListBox.count was usually wrong. There might be 25 files in the folder, byut it wouls say there were 15, for example.When I tested the program further I found it would not copy all of the files it shoulod. If there were 300 files inthe source folder, it should copy 150 of them. It might copy only 125 of them for example. I could find nothingdifferent (such as attributes) about the files it would not count or copy. But it seemed to usually make exacty the same mistakes on the same folders.. Then I took the .exe to another Windows 7 computer, my video/animation computer. My program worked flawlessly on this computer, always giving the correct file count, and copying every other file perfectly. Another program I had started was having problems.  don't remember details now, but a component wasn't behaving correctly. I finally started the program over again from scratch and the problem was gone.
Now I am working on a program to display a picture for a special purpose, the .exe, to another computer running Windows XP. When I first tried it selecting an image instantly made the image appear in the Timage on both main and child forms. But then it wouldn't change. I had only two .bmp images inthe folder to test with. I closed it and opened it again. Now it worked perfectly. I could select rither picture and they would be instantly displayed on both timages. It woulod change both images when I selected them. Then I closed it and later added some .jpg files to the folder. I went to test it again. Now it displayed the first selection on the main form, but then wouldn't change the image again. It did change on the child form, which always seems to work perfectly. I closed it and opened it again. Now the main form Timage would never display a picture again. I closed and opened the program several times. It would always display to the timage on the child form perfectly, but would no longer ever display an image on the main form. I closed and re-opened the program many times and it would never show either a .bmp or .jpg in the timage ion the main form. I tried it agaion this moring and now it will display the first selected image in the timage on the main form, but then will never change as I select images with the child form. The Timage on the child form always displays the selected image.
So what do you think ? Bad Delphi installation ? Is Delphi 2011 out yet ?
0
 
LVL 14

Expert Comment

by:systan
ID: 35122119
try to add in uses;
jpeg

{$R *.dfm}
uses jpeg;

procedure TForm2.Button1Click(Sender: TObject);
var filepath: string;
begin

filepath :='c:\x.jpg'; //jpeg image test
Form2.image1.Picture.LoadFromFile(filepath); //formStyle sMDIChild
Form1.Image1.Picture.LoadFromFile(filepath); //formStyle sMDIForm

//or

{
filepath := 'c:\y.bmp'; //bmp image test
Form2.image1.Picture.LoadFromFile(filepath);//formStyle sMDIChild
Form1.Image1.Picture.LoadFromFile(filepath);//formStyle sMDIForm
}
end;

Open in new window


Because, maybe you have already assign in the imagebox a bitmap image and the other form is assigned jpeg image, then you didn't clear the box.  Try to check it.
0
 

Author Comment

by:ChLa
ID: 35122536
I tried adding jpeg to uses on the child form. It was already in uses on the main form. This didn't help.
Your lines assigning filepath seem to select a random .jpeg or bmp. My program already can select a vaiid jpeg's filepath, so I didn't add this part of your suggestion. I know I have a valid file and filepath because the timage on the child form displays it when I select it. It will display the same image in the timage on the parent form if I select it at runtime, or sometimes if I move the .exe to another computer. On this computer I have only a folder with five jpegs. So I didn't use the second part of your procedure. The other two lines are exactly like mine except you said Form2 instead of MainForm. Delphi doesn't see a Form2, so I had to substitute MainForm to get it to complie. Now the two lines are exactly what I already had. It didn't help. I didn't try your three lines for a .bmp, because this laptop only has the five .jpegs in a folder. I have the filelistbox pointing to a specific directory because in the final version of the program, I want the user to only be able to use specific images I have put into that specific folder.
Note that these lines of code are in the child form, which is Form1 (Unit1), not in the main form (Main).
0
 

Author Comment

by:ChLa
ID: 35122562
This is really only a very short simple program that is the beginning of a new project. I got stuck at the beginning of the project with this problem.
Here is the code for the Main Form:

unit MAIN;

interface

uses Windows, SysUtils, Classes, Graphics, Forms, Controls, Menus,
  StdCtrls, Dialogs, Buttons, Messages, ExtCtrls, ComCtrls, StdActns,
  ActnList, ToolWin, ImgList, jpeg;

type
  TMainForm = class(TForm)
    MainMenu1: TMainMenu;
    File1: TMenuItem;
    Help1: TMenuItem;
    N1: TMenuItem;
    FileExitItem: TMenuItem;
    HelpAboutItem: TMenuItem;
    OpenDialog: TOpenDialog;
    Button1: TButton;
    Button2: TButton;
    SelectImage1: TMenuItem;
    Image1: TImage;
    procedure FileNew1Execute(Sender: TObject);
    procedure FileOpen1Execute(Sender: TObject);
    procedure HelpAbout1Execute(Sender: TObject);
    procedure FileExit1Execute(Sender: TObject);
    procedure SelectImage1Click(Sender: TObject);
    procedure Button1Click(Sender: TObject);
  private
    { Private declarations }
    procedure CreateMDIChild(const Name: string);
  public
    { Public declarations }
  end;

var
  MainForm: TMainForm;

implementation

{$R *.dfm}

uses CHILDWIN, about, Unit1;

procedure TMainForm.Button1Click(Sender: TObject);
begin
  Image1.Picture.LoadFromFile(FilePath);
  Button1.Caption := FilePath;
end;

procedure TMainForm.CreateMDIChild(const Name: string);
var
  Child: TMDIChild;
begin
  { create a new MDI child window }
  Child := TMDIChild.Create(Application);
  Child.Caption := Name;
  if FileExists(Name) then Child.Memo1.Lines.LoadFromFile(Name);
end;

procedure TMainForm.FileNew1Execute(Sender: TObject);
begin
  CreateMDIChild('NONAME' + IntToStr(MDIChildCount + 1));
end;

procedure TMainForm.FileOpen1Execute(Sender: TObject);
begin
  if OpenDialog.Execute then
    CreateMDIChild(OpenDialog.FileName);
end;

procedure TMainForm.HelpAbout1Execute(Sender: TObject);
begin
  AboutBox.ShowModal;
end;

procedure TMainForm.SelectImage1Click(Sender: TObject);
begin
  Form1.Visible := True;
end;

procedure TMainForm.FileExit1Execute(Sender: TObject);
begin
  Close;
end;

end.
0
 

Author Comment

by:ChLa
ID: 35122588
This is the code for the child form:

unit Unit1;

interface

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

type
  TForm1 = class(TForm)
    FileListBox1: TFileListBox;
    Panel1: TPanel;
    Panel2: TPanel;
    Image1: TImage;
    procedure Panel1Click(Sender: TObject);
    procedure FormCreate(Sender: TObject);
    procedure FileListBox1Click(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
  end;

var
  Form1: TForm1;
  FilePath: String;

implementation

uses MAIN, jpeg;

{$R *.dfm}

procedure TForm1.FileListBox1Click(Sender: TObject);
begin
  Panel2.Caption := FileListBox1.FileName;    //shows the selected file, for debugging
  FilePath := FileListBox1.FileName;
  Image1.Picture.LoadFromFile(FilePath);      //This works
  MainForm.Image1.Picture.LoadFromFile(FilePath);     //This doesn't
end;

procedure TForm1.FormCreate(Sender: TObject);
begin
  FileListBox1.Directory := 'C:\CLs Files\Images';    //points our filelistbox to the folder with our images
end;

procedure TForm1.Panel1Click(Sender: TObject);
begin
  Form1.Visible := False;       //close picture selector
end;

end.
0
How your wiki can always stay up-to-date

Quip doubles as a “living” wiki and a project management tool that evolves with your organization. As you finish projects in Quip, the work remains, easily accessible to all team members, new and old.
- Increase transparency
- Onboard new hires faster
- Access from mobile/offline

 
LVL 9

Expert Comment

by:Mahdi78
ID: 35122919
Put CreateMDIChild in public declarations like this

  private
    { Private declarations }
  public
    { Public declarations }
  procedure CreateMDIChild(const Name: string);
  end;
0
 
LVL 14

Expert Comment

by:systan
ID: 35123038
Did you try like this;
procedure TForm1.FileListBox1Click(Sender: TObject);
begin
  Panel2.Caption := FileListBox1.FileName;    //shows the selected file, for debugging
  FilePath := FileListBox1.FileName;
  Image1.Picture.LoadFromFile(FilePath);      //This works
  //changes here
  MainForm.Image1.Picture := Form1.Image1.Picture;

end;
0
 
LVL 14

Expert Comment

by:systan
ID: 35123042
//or
MainForm.Image1.Picture := Image1.Picture;
0
 

Author Comment

by:ChLa
ID: 35124322
I tried adding CreateMDIChild to the public declarations. It was a matter of moving it down a few lines from the private declarations. It seems to make no difference.
I also tried the next two suggestions, changing to := Form1.Image1.Picture; and  := Image1.Picture;
These also seem to have made no difference. Nothing is being displayed in the TImage on the main form.
 
0
 
LVL 14

Expert Comment

by:systan
ID: 35124538
I have made changes to your code,   and it works good now,    but I will not post it until you closed your other questions.    Seems that your not accepting good comment as good answers.    Please look at your other questions.    It has been answered well by professional experts here, and you are not paying attention.
0
 
LVL 14

Expert Comment

by:systan
ID: 35125299
Here's the test I have;
mditest.exe
0
 
LVL 37

Expert Comment

by:Geert Gruwez
ID: 35129226
@systan ... an exe ?
nobody can read binary ...

@ChLa
The fact that you are using Form1 and MainForm has already been pointed out as not very good.
In fact it's really bad ... circular unit reference is just another bad fix to get around this problem

O, one other thing, ... your child form doesn't necessarily have the name Form1
it could be Form2, Form3, Form3452452342542345 or name = ''
so ... never use Form1.Visible := false;
instead: Self.Visible := False;

you can have multiple children forms
and you want to set the main form image to that of the last loaded in 1 of the child forms
very odd

i would use a callback function to do that
change unit 1 as follows:
unit Unit1;

interface

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

type
  TImageCallback = procedure (Sender: TObject; Img: TPicture) of object;

  TForm1 = class(TForm)
    FileListBox1: TFileListBox;
    Panel1: TPanel;
    Panel2: TPanel;
    Image1: TImage;
    procedure Panel1Click(Sender: TObject);
    procedure FormCreate(Sender: TObject);
    procedure FileListBox1Click(Sender: TObject);
  private
    fImageCallback: TImageCallback;
  public
    constructor Create(AOwner: TComponent; aImageCallback: TImageCallback); reintroduce; 
  end;

var
  Form1: TForm1;
  FilePath: String;

implementation

uses jpeg;

{$R *.dfm}

constructor TForm1.Create(AOwner: TComponent; aImageCallback: TImageCallback); 
begin
  inherited Create(AOwner);
  fImageCallback := aImageCallback;
end;

procedure TForm1.FileListBox1Click(Sender: TObject);
begin
  Panel2.Caption := FileListBox1.FileName;    //shows the selected file, for debugging
  FilePath := FileListBox1.FileName;
  Image1.Picture.LoadFromFile(FilePath);      //This works
  if Assigned(fImageCallback) then 
    fImageCallback(Image1.Picture);
end;

procedure TForm1.FormCreate(Sender: TObject);
begin
  FileListBox1.Directory := 'C:\CLs Files\Images';    //points our filelistbox to the folder with our images
end;

procedure TForm1.Panel1Click(Sender: TObject);
begin
  Self.Visible := False;       //close picture selector
end;

end.

Open in new window


where do you create Form1 ? is this autocreate ?
do you want Form1 as mdichild ?
very obscure ...

change main unit as
 
unit MAIN;

interface

uses Windows, SysUtils, Classes, Graphics, Forms, Controls, Menus,
  StdCtrls, Dialogs, Buttons, Messages, ExtCtrls, ComCtrls, StdActns,
  ActnList, ToolWin, ImgList, jpeg;

type
  TMainForm = class(TForm)
    MainMenu1: TMainMenu;
    File1: TMenuItem;
    Help1: TMenuItem;
    N1: TMenuItem;
    FileExitItem: TMenuItem;
    HelpAboutItem: TMenuItem;
    OpenDialog: TOpenDialog;
    Button1: TButton;
    Button2: TButton;
    SelectImage1: TMenuItem;
    Image1: TImage;
    procedure FileNew1Execute(Sender: TObject);
    procedure FileOpen1Execute(Sender: TObject);
    procedure HelpAbout1Execute(Sender: TObject);
    procedure FileExit1Execute(Sender: TObject);
    procedure SelectImage1Click(Sender: TObject);
    procedure Button1Click(Sender: TObject);
  private
    procedure CreateMDIChild(const Name: string);
    procedure ImageCallback(Sender: TObject; Img: TPicture);
  public
    { Public declarations }
  end;

var
  MainForm: TMainForm;

implementation

{$R *.dfm}

uses ChildWin, about, Unit1;

procedure TMainForm.Button1Click(Sender: TObject);
begin
  Image1.Picture.LoadFromFile(FilePath);
  Button1.Caption := FilePath;
end;

procedure TMainForm.CreateMDIChild(const Name: string);
var
  Child: TMdiChild;
begin
  { create a new MDI child window }
  Child := TMdiChild.Create(Self, ImageCallback);
  Child.Caption := Name;
  if FileExists(Name) then Child.Memo1.Lines.LoadFromFile(Name);
end;

procedure TMainForm.FileNew1Execute(Sender: TObject);
begin
  CreateMDIChild('NONAME' + IntToStr(MDIChildCount + 1));
end;

procedure TMainForm.FileOpen1Execute(Sender: TObject);
begin
  if OpenDialog.Execute then
    CreateMDIChild(OpenDialog.FileName);
end;

procedure TMainForm.HelpAbout1Execute(Sender: TObject);
begin
  AboutBox.ShowModal;
end;

procedure TMainForm.SelectImage1Click(Sender: TObject);
begin
  if Assigned(Form1) then 
    Form1.Visible := True;
end;

procedure TMainForm.FileExit1Execute(Sender: TObject);
begin
  Close;
end;

procedure TMainForm.btnCreateForm1Click(Sender: TObject);
begin
  if Assigned(Form1) then 
    FreeAndNil(Form1);
  Form1 := TForm1.Create(Self, ImageCallBack);
end;

procedure TMainForm.ImageCallback(Sender: TObject; Img: TPicture);
begin
  Image1.Picture := Img;
end;


end.

Open in new window

0
 
LVL 14

Expert Comment

by:systan
ID: 35130004
hi
Geert;

>>nobody can read binary ...
The reason why I attached the binary file, because; of this comments;
http://www.experts-exchange.com/Programming/Languages/Pascal/Delphi/Q_26882482.html#35124538

I hope you understand.
0
 
LVL 14

Expert Comment

by:systan
ID: 35130181
Good ChLa has accepted right answers on his previous questions.
Now, where back;
The only Line missing to display the Mainform image from the child form is;
MainForm.ReAlign;

procedure TForm1.FileListBox1Click(Sender: TObject);
begin
  Panel2.Caption := FileListBox1.FileName;    //shows the selected file, for debugging
  FilePath := FileListBox1.FileName;
  Image1.Picture.LoadFromFile(FilePath);      //This works
  
////changes here////
  MainForm.Image1.Picture := Image1.Picture;[b]MainForm.ReAlign;[/b]

end;

Open in new window

0
 
LVL 14

Accepted Solution

by:
systan earned 125 total points
ID: 35130380
hi ChLa;

Looking at your other post,  the way I see when you accept right comments are those who are first commented your post,  which is wrong,  you only click the accept button if that is the right person or expert answer.   Please read the names of the expert first before clicking the accept button.


I hope you have your code corrected by now.

Just only 1 line, which is;
Mainform.Realign;


procedure TForm1.FileListBox1Click(Sender: TObject);
begin
  Panel2.Caption := FileListBox1.FileName;    //shows the selected file, for debugging
  FilePath := FileListBox1.FileName;
  Image1.Picture.LoadFromFile(FilePath);      //This works
  
////changes here////
  MainForm.Image1.Picture := Image1.Picture;
  MainForm.Realign;

end;

Open in new window

0
 
LVL 37

Expert Comment

by:Geert Gruwez
ID: 35135511
systan, and others, it is bad, bad, bad, bad, very very very bad to use reference to mainform instance in other units
please stop giving people advice like that

unless ...
you are trying to educate people in doing things wrong,
so they will come back with more questions for the right way

i can not stress this enough
this is the worst bug in delphi has aloud since man invented the gun
0
 
LVL 14

Expert Comment

by:systan
ID: 35136096
Actually it's not a Delphi bug, it's a Delphi designed.
That's there system.
0
 
LVL 14

Expert Comment

by:systan
ID: 35139707
Ops, >>it's a Delphi designed.
No it's not, it's the Borland designed, followed by CodeGear, then Embarcadero without looking it.
0
 
LVL 37

Expert Comment

by:Geert Gruwez
ID: 35141606
it's a hole developers found and wrongly used
btw
you forgot Inprise
0
 

Author Closing Comment

by:ChLa
ID: 35157454
I started with the easiest looking solution, and it worked. I will review the rest and I thank everyone for their help. I appreciate all the input.
0

Featured Post

What Is Threat Intelligence?

Threat intelligence is often discussed, but rarely understood. Starting with a precise definition, along with clear business goals, is essential.

Join & Write a Comment

Suggested Solutions

Introduction The parallel port is a very commonly known port, it was widely used to connect a printer to the PC, if you look at the back of your computer, for those who don't have newer computers, there will be a port with 25 pins and a small print…
Creating an auto free TStringList The TStringList is a basic and frequently used object in Delphi. On many occasions, you may want to create a temporary list, process some items in the list and be done with the list. In such cases, you have to…
Excel styles will make formatting consistent and let you apply and change formatting faster. In this tutorial, you'll learn how to use Excel's built-in styles, how to modify styles, and how to create your own. You'll also learn how to use your custo…
Get a first impression of how PRTG looks and learn how it works.   This video is a short introduction to PRTG, as an initial overview or as a quick start for new PRTG users.

746 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

10 Experts available now in Live!

Get 1:1 Help Now