Recent

Author Topic: Asking for: tips on when/how to populate a form with data upon creation  (Read 6974 times)

WalterK

  • New Member
  • *
  • Posts: 48
Hi,

I'm pretty new to the ins and outs of windowing programming.  I'm wanting to populate a form with data after creation - reading in data from the last file opened and painting that into the fields.  But I keep getting errors - access violations.  The code will work fine if I call it after the program is up and running.

Reading a bit on this, I see I might need a sleeper thread to populate the form's fields after its all created... true?  Is there no event to hang this on?

(If so, suggestion: add a "PAINTED" event to use for these kinds of things.)

Thanks.

Blaazen

  • Hero Member
  • *****
  • Posts: 3241
  • POKE 54296,15
    • Eye-Candy Controls
If you have some code in OnCreate event and it gives you errors then you can move this code to OnActivate - it will be done later.
To ensure that code will run only once, you can add:
Code: [Select]
OnActivate:=nil;
to the end of OnActivate method.
Lazarus 2.3.0 (rev main-2_3-2863...) FPC 3.3.1 x86_64-linux-qt Chakra, Qt 4.8.7/5.13.2, Plasma 5.17.3
Lazarus 1.8.2 r57369 FPC 3.0.4 i386-win32-win32/win64 Wine 3.21

Try Eye-Candy Controls: https://sourceforge.net/projects/eccontrols/files/

JuhaManninen

  • Global Moderator
  • Hero Member
  • *****
  • Posts: 4695
  • I like bugs.
OnActivate may help, I don't know.
Anyway this has always been a problem with Delphi. OnCreate and OnShow were called too early (don't remember about OnActivate).
The normal solution was to fire a user defined message from OnCreate or from OnShow. The message handler was called by Windows after the form was painted. For a cross platform application a Windows message is not the best option. Lazarus seems to use OnIdle handlers for such things in many places. Please do "Find in Files" and search for OnIdle from Lazarus source for examples.
Mostly Lazarus trunk and FPC 3.2 on Manjaro Linux 64-bit.

mas steindorff

  • Hero Member
  • *****
  • Posts: 566
Your right about the need to delay but I've had issues with the oncreate, aftercreate, and onactivate code as well.  (mostly when I need to access hardware via a DLL)
The best way that works for me is to drop a timer on the form, set it to run 500ms and set as active using the object editer. Then place the hardware access (open file) code in the ontimer event.  be sure to disable the timer so it acts like a one shot. 
windows 10 &11, Ubuntu 21+ IDE 3.4 general releases

sfeinst

  • Sr. Member
  • ****
  • Posts: 258
If you are loading data just when app starts, the way I do this is in the main lpr file, after the call to Application.CreateForm, I place a call to my own method on the form.  That method then populates the form data.  So far it has worked fine for me.

Bart

  • Hero Member
  • *****
  • Posts: 5706
    • Bart en Mariska's Webstek
Try QueueAsyncCall in OnActivate (?)

Code: [Select]
type
    TForm1 = Class(TForm)
    ...
    procedure DoSomething(DummyParam: PtrInt);
    ...
    end;//declaration of TForm
   ...
   implementation
  ...
procedure TForm1.FormActivate(Sender: TObject);
begin
  Application.QueueAsyncCall(@DoSomething, 0);
  OnActivate := nil;
end;

Now DoSomething will be done after the form is shown.
You might want it in OnShow instead.

Bart

WalterK

  • New Member
  • *
  • Posts: 48
Thanks for the suggestions.

I intend to run this cross-platform so I can't use a Windows-only solution.

Calling the code from the OnActivate didn't fix the problem. (I had tried initializing from the OnCreate, OnShow, OnPaint, OnResize, and maybe some others before I posted.)

I had already tried (and tried again, just to be sure) calling the code from the main .lpr file after the CreateForm calls - still got the error.  (It must be that CreateForm kicks off threads and doesn't wait for completion.)

(To be more complete, in case it sheds light on Lazarus inner-workings: I was loading a TLabel with a file name - which works - and then reading a file to load other TEdit fields - that didn't work.  Go figure.)

The timer solution probably would work, but I chose the QueueAsyncCall solution and it works fine.  Thank you.

Thank you all.

(So why can't Lazarus have it's own 'TheFormHasBeenFullyCreatedAndIsReadyToBeInitialized' routine so as to make everyone's life easier?  Oh, well.)

Walter
« Last Edit: June 23, 2011, 05:07:49 pm by WalterK »

mas steindorff

  • Hero Member
  • *****
  • Posts: 566
Thanks for the suggestions.
...
The timer solution probably would work, but I chose the QueueAsyncCall solution and it works fine.  Thank you.

Thank you all.

(So why can't Lazarus have it's own 'TheFormHasBeenFullyCreatedAndIsReadyToBeInitialized' routine so as to make everyone's life easier?  Oh, well.)

Walter
From what I found a few years ago with Delphi is it's not the pascal code but the OS DLL.  Different hardware drivers cycle though 3 states at start-up, DETECT HW, INIT_HW, ACTIVE_HW (as an example).  Each state needs some real time so the driver can gain access to the "bus" or wait for the HW to power up or change state.  These older DLLs did not respond quite right when the SW tried to ACCESS_HW before the start-up states were complete.  I have not looked into this issue since I found the timer solution so this could be old news but the timer solution continues to work for me whether it's the DLL delay or if it's just letting the pascal event handler get up and running that's the issue.
windows 10 &11, Ubuntu 21+ IDE 3.4 general releases

 

TinyPortal © 2005-2018