Recent

Author Topic: Second Form for illustrations  (Read 1212 times)

CharlesMGoldie

  • Newbie
  • Posts: 6
Second Form for illustrations
« on: February 27, 2025, 01:01:30 am »
I have a working GUI program that asks the user for a file, does some calculations on it and puts the results in a text file.  I want to set up a second Form in which, without further input from the user, I can illustrate the results by issuing some of the form's Canvas commands.

I've followed the tutorial https://wiki.freepascal.org/Form_Tutorial and so have set up the second Form, with each Form having a button to switch to the other.  My query is how and where to declare a procedure Drawit, or possibly Form2.Drawit or even Form1.Drawit, and how and where to call this procedure.

I've added Unit2 to the uses section of Unit1, and in defining the button click procedure in Unit1 I've followed the command Form2.ShowModal with a command Form2.Drawit.

In the interface of Unit2 I've declared procedure Drawit in the public part of the TForm2 type definition.  Then in Unit2's implementation section
I define the procedure TForm2.Drawit to issue the command TForm2.Canvas.LineTo(500,500).  But this produces the errors on compilation "Only class methods, class properties and class variables can be referred with class references" and "Only class methods, class properties and class variables can be accessed in class methods".

Apologies for this query from a GUI newbie (although an occasional Pascal programmer since 1976, and before that Algol60 and Algol68 since 1973).

dseligo

  • Hero Member
  • *****
  • Posts: 1674
Re: Second Form for illustrations
« Reply #1 on: February 27, 2025, 02:51:58 am »
I define the procedure TForm2.Drawit to issue the command TForm2.Canvas.LineTo(500,500).  But this produces the errors on compilation "Only class methods, class properties and class variables can be referred with class references" and "Only class methods, class properties and class variables can be accessed in class methods".

TForm2 is a type. You can call it in one of these ways:
Code: Pascal  [Select][+][-]
  1. procedure TForm2.Drawit;
  2. begin
  3.   Self.Canvas.LineTo(500,500);
  4.   // or Canvas.LineTo(500,500);
  5.   // or Form2.Canvas.LineTo(500,500); // Form2 is variable with type TForm2
  6. end;

Jonny

  • Full Member
  • ***
  • Posts: 144
Re: Second Form for illustrations
« Reply #2 on: February 27, 2025, 04:00:36 am »
@CharlesMGoldie the attached project should answer your questions.

egsuh

  • Hero Member
  • *****
  • Posts: 1760
Re: Second Form for illustrations
« Reply #3 on: February 27, 2025, 05:16:43 am »
Or you may execute DrawIt at OnShow event.

Code: Pascal  [Select][+][-]
  1. procedure TForm2.FormShow(Sender: TObject);
  2. begin
  3.    DrawIt;
  4. end;
  5.  

CharlesMGoldie

  • Newbie
  • Posts: 6
Re: Second Form for illustrations
« Reply #4 on: February 28, 2025, 03:03:39 pm »
Sincere thanks to dselogo, Jonny and egsuh for the help.  However I still have problems.

dselogo.  Unfortunately, while each of your replacements for my illegal command TForm2.Canvas.LineTo(500,500) clears the compilation error, nothing is then drawn on Form2.

Jonny.  Thanks for the zipfile, with the use of an Image and its Canvas commands in my Drawit procedure.  Compilation is fine but when running the executable and clicking on the button to switch to Form2 I get a fatal Error: "project1 raised exception class 'External: SIGSEV' in file 'include\customimage.inc' at line 46".

egsuh.  Following your suggestion I declared procedure FormShow(Sender: TObject) in the interface part of Unit2, and defined it as you suggested in the implementation part.  Compilation is fine but on the run, nothing is drawn on Form2.

The problem is not with the simple command Canvas.LineTo(500,500), as it works on Form1 if I create Button2 there and define its Button2Click action to issue this command.

All I'm trying to do is to have a button on Form1 that when clicked, creates and shows Form2 and draws something on it, without further user input. I'd appreciate some further help.

Jonny

  • Full Member
  • ***
  • Posts: 144
Re: Second Form for illustrations
« Reply #5 on: February 28, 2025, 03:20:39 pm »
Quote from: CharlesMGoldie
Jonny.  Thanks for the zipfile, with the use of an Image and its Canvas commands in my Drawit procedure.  Compilation is fine but when running the executable and clicking on the button to switch to Form2 I get a fatal Error: "project1 raised exception class 'External: SIGSEV' in file 'include\customimage.inc' at line 46".

My project did not contain a customimage.inc file - please share your project so that we can see where you are calling it from.

Quote from: CharlesMGoldie
The problem is not with the simple command Canvas.LineTo(500,500), as it works on Form1 if I create Button2 there and define its Button2Click action to issue this command.

All I'm trying to do is to have a button on Form1 that when clicked, creates and shows Form2 and draws something on it, without further user input. I'd appreciate some further help.

Not possible, the second form will repaint itself, that is why I added the TImage to overcome the repaint issues.

zeljko

  • Hero Member
  • *****
  • Posts: 1883
    • http://wiki.lazarus.freepascal.org/User:Zeljan
Re: Second Form for illustrations
« Reply #6 on: February 28, 2025, 04:01:19 pm »
Or you may execute DrawIt at OnShow event.

Code: Pascal  [Select][+][-]
  1. procedure TForm2.FormShow(Sender: TObject);
  2. begin
  3.    DrawIt;
  4. end;
  5.  

This is wrong, you're painting outside of paint event. DrawIt should be called inside Form.OnPaint event, and eg in button click you should call Invalidate;

LV

  • Sr. Member
  • ****
  • Posts: 427
Re: Second Form for illustrations
« Reply #7 on: February 28, 2025, 04:33:13 pm »
Yes. All Canvas operations must be performed ONLY in OnPaint handlers.
Use Invalidate instead of direct calls:
Invalidate marks the form as "dirty" (needing repaint).
The actual DrawIt call occurs later when the system processes the message queue.
Safer than direct calls, as it ensures the correct device context for drawing.
For example:

egsuh

  • Hero Member
  • *****
  • Posts: 1760
Re: Second Form for illustrations
« Reply #8 on: March 01, 2025, 11:16:07 am »
I do not know much about painting (other subjects either), and I could make procedure DrawIt run at the opening of Form1. But no more. I cannot run it with FormResize.

Code: Pascal  [Select][+][-]
  1. procedure TForm1.FormPaint(Sender: TObject);
  2. begin
  3.    DrawIt;
  4. end;
  5.  
  6. procedure TForm1.FormShow(Sender: TObject);
  7. begin
  8.    Repaint;
  9. end;
  10.  
  11. procedure TForm1.DrawIt;
  12. begin
  13.    Canvas.LineTo(500,500);
  14. end;
  15.  

CharlesMGoldie

  • Newbie
  • Posts: 6
Re: Second Form for illustrations
« Reply #9 on: March 01, 2025, 04:23:41 pm »
@Jonny The zip of my project modified to include your lines with Image is below.  This is not from loading the project in your secondform.zip into Lazarus, as when I did that and attempted to compile, a message "Cannot compile project" with "The project has no main source file" appeared, which I don't understand at all.  I'm running Lazarus 2.0.12 under Windows10.

The zipfile secondformCMG.zip below is thus of my original project as I originally posted about, with your code about Image keyboarded in.  When compiled, this results in the runtime error (exception class) 'External: SIGSEV' at line 46 of customimage.inc.  The file customimage.inc is part of the LCL: lazarus\lcl\include\customimage.inc.

I'll be very happy to use Image if it can be got to work.

@zeljko and @LV Thanks for the input and for telling me about Invalidate; I appreciate I need to call it.

With Project1.zip supplied by LV I have the same problem, that Lazarus claims there is no main source file and gives up.  Copying project1.lpr, unit1.pas and unit2.pas into my project gives the zipfile Project1CMG.zip attached below, and this compiles and runs.  Unfortunately there is nothing drawn in Form2. It stays blank.

I can't see where the FormPaint procedure in Unit2 gets called, and assume that one or other of the calls of Form2.Show and Form2.Invalidate do so, silently.

I'd appreciate further help.






Jonny

  • Full Member
  • ***
  • Posts: 144
Re: Second Form for illustrations
« Reply #10 on: March 01, 2025, 05:25:38 pm »
@CharlesMGoldie, you had removed the TImage from the second form but were still trying to access it, hence the exception. Updated project attached.

LV

  • Sr. Member
  • ****
  • Posts: 427
Re: Second Form for illustrations
« Reply #11 on: March 01, 2025, 05:38:10 pm »

With Project1.zip supplied by LV I have the same problem, that Lazarus claims there is no main source file and gives up.  Copying project1.lpr, unit1.pas and unit2.pas into my project gives the zipfile Project1CMG.zip attached below, and this compiles and runs.  Unfortunately there is nothing drawn in Form2. It stays blank.


Follow these steps in your Project1CMG project: 
1. Open Project1CMG in Lazarus. 
2. Switch to Form2. 
3. In the Object Inspector, go to the Events tab. 
4. Find the OnPaint event and double-click it
5. Run the project (or by pressing F9). 
It should work.  :)
« Last Edit: March 01, 2025, 05:43:58 pm by LV »

CharlesMGoldie

  • Newbie
  • Posts: 6
Re: Second Form for illustrations
« Reply #12 on: March 02, 2025, 11:35:50 am »
@Jonny Many thanks.  I hadn't realised that as well as getting the code right, I needed to drop a TImage control onto Form2 in the Object Inspector.  Success at last!

@LV Thanks also.  I hadn't known how to find the On... handlers and change them.  My OnPaint handler now calls FormPaint.  On compiling and running the program I still get nothing painted in Form2.  However I'm inclined to leave it at that, as from Jonny I have the successful method of using an Image (TImage) within which to draw my illustration.  In fact I'm not sure I need Form2 after all, as I could simply enlarge Form1 and have an Image within it.

I hope this topic will be useful to some other GUI novices, as it certainly has been to me.

 

TinyPortal © 2005-2018