Recent

Author Topic: [Solved!] Weird behaviour in FormCreate  (Read 5901 times)

heebiejeebies

  • Full Member
  • ***
  • Posts: 129
[Solved!] Weird behaviour in FormCreate
« on: August 07, 2021, 12:50:10 am »
Hi all,

I recently wrote a routine to load user preferences from an SQL file at load time.  I put the code in the FormCreate procedure of Form1.  Most of it works well, except for the following strange behaviour.  Currently I only have 3 preferences, and after loading the data and placing it into global variables, I then need to update the preferences screen (which is Unit2) to correctly reflect the settings.

Code: Pascal  [Select][+][-]
  1. PreferencesForm.DefaultHomeScreen.Text := DefaultHomeScreenPref;
  2. If OpenModuleWalkThroughPref = 'True' then PreferencesForm.OpenModuleWalkThrough.Checked := true;
  3. PreferencesForm.UserFilesDirectoryField.text := UserFilesDirPref;
  4.  

Now the strange thing is, this works perfectly fine if I put the code into a button on Form1.  But if I put it in the FormCreate procedure then, it still compiles, but I get the following error:

"Project raised exception class 'External: SIGSEGV'.

 In file 'unit1.pas' at line 1411:
PreferencesForm.DefaultHomeScreen.Text := DefaultHomeScreenPref;"

 :o

I even tried calling the button procedure from within the FormCreate procedure, but the same thing happens. If I comment out the first line of the code, then it complains about the second, and so on.  What the...?
« Last Edit: August 07, 2021, 02:30:03 am by heebiejeebies »
Fedora 38/Lazarus 2.2.4- FPC 3.3.1

engkin

  • Hero Member
  • *****
  • Posts: 3112
Re: Weird behaviour in FormCreate
« Reply #1 on: August 07, 2021, 01:22:04 am »
I guess the other for is *not* created yet?

heebiejeebies

  • Full Member
  • ***
  • Posts: 129
Re: Weird behaviour in FormCreate
« Reply #2 on: August 07, 2021, 01:49:41 am »
That's probably it - but still a bit confusing because when I call it through the button, the form is not yet visible either.  It only becomes visible when you call it through the Preferences option in the menubar.  So I would have assumed that FormCreate would not be called for Unit2 until that point anyway.

But that gives me a possible solution of just adding the code to the Menuitem procedure.  Let me see how that goes.  Thanks!
Fedora 38/Lazarus 2.2.4- FPC 3.3.1

engkin

  • Hero Member
  • *****
  • Posts: 3112
Re: Weird behaviour in FormCreate
« Reply #3 on: August 07, 2021, 01:58:11 am »
We don't need to guess, just check the form variable. If nil or not

Based on your settings your forms will get created one after the other. I believe your code is in the main form. That means when you run your code in OnCreate event, no other form is created yet.
« Last Edit: August 07, 2021, 02:07:06 am by engkin »

lucamar

  • Hero Member
  • *****
  • Posts: 4219
Re: Weird behaviour in FormCreate
« Reply #4 on: August 07, 2021, 02:19:09 am »
That's probably it - but still a bit confusing because when I call it through the button, the form is not yet visible either.  It only becomes visible when you call it through the Preferences option in the menubar.  So I would have assumed that FormCreate would not be called for Unit2 until that point anyway.

FormCreate is called when the form is ... well, created. It has nothing to do with whether it's shown (i.e., "visible") or not; it's perfectly "legal" to create a form but don't show it until later (if ever!).

You can test this yourself: create a new application with two forms and make sure both of them are in the "auto-create" list, but set the second form's (the one that is NOT the application's MainForm) "Visible" property to False in the Object Inspector. Then run the application ;)
Turbo Pascal 3 CP/M - Amstrad PCW 8256 (512 KB !!!) :P
Lazarus/FPC 2.0.8/3.0.4 & 2.0.12/3.2.0 - 32/64 bits on:
(K|L|X)Ubuntu 12..18, Windows XP, 7, 10 and various DOSes.

heebiejeebies

  • Full Member
  • ***
  • Posts: 129
Re: Weird behaviour in FormCreate
« Reply #5 on: August 07, 2021, 02:27:47 am »
Thanks guys!  Well that was a pretty simple answer to a baffling problem.

My solution was just to put the code in the Preferences menuitem, and it works fine.  :D
Fedora 38/Lazarus 2.2.4- FPC 3.3.1

lucamar

  • Hero Member
  • *****
  • Posts: 4219
Re: [Solved!] Weird behaviour in FormCreate
« Reply #6 on: August 07, 2021, 03:44:47 am »
Another solution is to defer those kind of initializations to the OnActivate event handler, though then you'll have to set some kind of flag to avoid doing it every time it's called or, if if it's the only it does, by making sure it gets called only once (by setting OnActivate := nil on entry to the handler).

But yes, if you can in fact wait until some menu item is clicked that's probaby the best solution ... with the same caveats as above re. making sure that (or similar) particular initialization code is called only once.
Turbo Pascal 3 CP/M - Amstrad PCW 8256 (512 KB !!!) :P
Lazarus/FPC 2.0.8/3.0.4 & 2.0.12/3.2.0 - 32/64 bits on:
(K|L|X)Ubuntu 12..18, Windows XP, 7, 10 and various DOSes.

dbannon

  • Hero Member
  • *****
  • Posts: 2791
    • tomboy-ng, a rewrite of the classic Tomboy
Re: [Solved!] Weird behaviour in FormCreate
« Reply #7 on: August 07, 2021, 09:30:51 am »
I think I would take a slightly different approach.  You initially were reading the preferences in form1's create  and poking some preference into form2. And hitting Form2 before its created.

A better way to do it is to keep those preferences in Form1 and in Form2's create, go and get them from Form1.

All the preferences can sit in Form1, perhaps as vars, maybe properties.  As your app scales up, that approach is essential.

Davo
Lazarus 3, Linux (and reluctantly Win10/11, OSX Monterey)
My Project - https://github.com/tomboy-notes/tomboy-ng and my github - https://github.com/davidbannon

wp

  • Hero Member
  • *****
  • Posts: 11912
Re: [Solved!] Weird behaviour in FormCreate
« Reply #8 on: August 07, 2021, 12:08:47 pm »
I would not do it this way. When all the settings are in Form1 then Form2 must "use" Form1 in order to get access to the settings. But on the other hand Form1 (which seems to be the main form) must "use" Form2 in order to display Form2: Form2 uses Form1, and Form1 uses Form2. Therefore we have a cyclic dependence. Lazarus can handle this situation when these units are put into the implementation's uses clause. But when a simular situation occurs with other units it could soon happen that the cyclic dependence cannot be handled any more and Lazarus will refuse to compile the project.

It's better to aim for a "star-like" dependence. In the center of the "star" there should be a unit "Globals" with all the project-wide type declarations and variables, among them the settings. Every unit is allowed to "use Globals". This way Form2 finds the settings without having to know Form1, and the cyclic dependence is avoided.

heebiejeebies

  • Full Member
  • ***
  • Posts: 129
Re: [Solved!] Weird behaviour in FormCreate
« Reply #9 on: August 09, 2021, 12:36:51 pm »
Thanks for the input guys!  I'm a little bit confused though... The way I was planning to do things is to read the prefs from the SQL file at startup, put them into the preferences screen upon the menu call, then save them back into the SQL file when the prefs box is saved.  It is modal, so it doesn't need to affect any behaviour of the program while it's open anyway.  Then obviously the main unit needs to reload and apply the SQL file once the prefs box is closed.  Is there a disadvantage to doing it this way?  I will probably have fewer than 10 preferences in the finished app so it seems to me that this is the simplest solution, and a workable one.
Fedora 38/Lazarus 2.2.4- FPC 3.3.1

jamie

  • Hero Member
  • *****
  • Posts: 6129
Re: [Solved!] Weird behaviour in FormCreate
« Reply #10 on: August 09, 2021, 11:09:33 pm »
Use the OnCreate in the last form in the auto create list.

The forms are created in the order they show in the auto created list and if you depend on items being valid before they show and user interacts with them you can use the last auto created form and take advantage of the OnCreate event there.

 That should work for you.
The only true wisdom is knowing you know nothing

 

TinyPortal © 2005-2018