[SOLVED] How to switch a Form from Show-mode to ShowModal() without flicker? lazarus / 31-LCL ---------------------------------------------------------------------- Hartmut · 2022-01-07 11:01 My program uses a 2nd Form to display some infos. Some of these infos need a couple of seconds to gather them. I want to display the 1st part immediately and add the 2nd part after it is ready to display. Therefore I use Show() to make the 1st part visible. After the 2nd part is displayed, I can switch the Form to modal-mode. The problem is, that before the ShowModal() a Hide() is required and between those 2 commands a flicker occurs. I want to avoid that flicker. I have this flicker only on Linux Ubuntu 18.04 but not on Windows 7. I use Lazarus 2.0.6 (but have the same results with 2.0.10). I attached a small compilable project. Thanks in advance. Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i // Extract from Unit1:procedure TForm1.Button1Click(Sender: TObject);   begin   Form2.display_Infos;   end; // Extract from Unit2:procedure TForm2.display_Infos;   begin   Memo1.Clear;   Memo1.Lines.Add('This are Infos part 1');   Show; {display Infos part 1}   Application.ProcessMessages; {neccessary to display Infos part 1}    sleep(2000); {simulates gathering Infos part 2}    Memo1.Lines.Add('This are Infos part 2');   Hide; {is neccessary before ShowModal()}   ShowModal; {a flicker occurs between Hide() and ShowModal()}   end; procedure TForm2.Button_ActionClick(Sender: TObject);   begin   // do some actions...   Close;   end; procedure TForm2.Button_CloseClick(Sender: TObject);   begin   Close;   end; ---------------------------------------------------------------------- balazsszekely · 2022-01-07 11:16 @Hartmut Show the form with FormX.ShowModal, then on FormShow event start a timer, like this: Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i procedure TFormX.FormShow(Sender: TObject);begin  Timer1.Interval := 300;  Timer1.Enabled := True;end; procedure TFormX.Timer1Timer(Sender: TObject);begin  Timer1.Enabled := False;  Memo1.Clear;  Memo1.Lines.Add('This are Infos part 1');   Self.Enabled := False; //prevent user to close form  try    //do lengthy process here    Memo1.Lines.Add('This are Infos part 2');  finally    Self.Enabled := True;  end;end; PS: On design time set Timer1.Enabled to false. ---------------------------------------------------------------------- Hartmut · 2022-01-07 12:14 Thanks a lot GetMem for your quick reply. Before I try to implement it, may I ask a question? Why do you recommend a timer for this? Is it not possible to do everything directly in FormShow() - or in FormActivate(), where I already had experimented with? Because I'm still a beginner to GUI programming I want to understand and to learn. Thanks. ---------------------------------------------------------------------- balazsszekely · 2022-01-07 13:14 @Hartmut QuoteThanks a lot GetMem for your quick reply.You are welcome! QuoteBefore I try to implement it, may I ask a question? Why do you recommend a timer for this? Because is the least painful solution. If you put a lengthy code in the FormShow event, the form won't be visible until the lengthy process is over. With a timer you immediately exit the OnShow event and the user will have a visual feedback. FormActivate is also OK, but you have to be careful because FormActivate is always called when the from receive focus. There are other ways to achieve the same thing, like running the lengthy code on FormCreate and showing a busy cursor in the caller form. In my opinion a timer is the most straightforward solution. ---------------------------------------------------------------------- Hartmut · 2022-01-07 13:52 Hello GetMem, thank you very much for your explanations. Meanwhile I implemented your suggestion. The good news is: no more flicker :-)) But the 2nd Form is not longer "really" modal: as long as it is open, you still can press Button1 from Form1 and get a Runtime-Error, because Form2 ist already displayed. I have this both on Lazarus 2.0.6 and 2.0.10. In my "original" demo version Button1 is blocked (in 2.0.6 and 2.0.10), as it should be for modal Forms. Here is my new code: Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i procedure TForm2.display_Infos;   begin   ShowModal; {calls FormShow()}   end; procedure TForm2.FormShow(Sender: TObject);   {Event "OnShow"}   begin   writeln('OnShow - start Timer');   Timer1.Interval := 300; {in ms}   Timer1.Enabled := True;   end; procedure TForm2.Timer1Timer(Sender: TObject);   {Event "OnTimer" des Timers}   begin   Timer1.Enabled := False;   writeln('Timer1Timer');    Memo1.Clear;   Memo1.Lines.Add('This are Infos part 1');   Application.ProcessMessages; {neccessary to display Infos part 1}    Self.Enabled := False; // prevent user to close form   try //do lengthy process here:       sleep(2000); {simulates gathering Infos part 2}       Memo1.Lines.Add('This are Infos part 2');   finally     Self.Enabled := True;   end; {try}   end; Did I made something wrong? ---------------------------------------------------------------------- balazsszekely · 2022-01-07 14:04 QuoteDid I made something wrong?No. At least noting obvious. I would suggest to remove method displayinfos and move the ShowModal part to your main form: Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i procedure TForm1.Button1Click(Sender: TObject);begin  Form2.ShowModal;end; If your second form(Form2) does not behave like a modal form, please attach your project or try something like this: Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i procedure TForm1.Button1Click(Sender: TObject);begin  Form1.Enabled := False;  try    Form2.ShowModal;  finally    Form1.Enabled := True;  end;end; The last method really shouldn't be necessary.  ShowModal always works fine for me. ---------------------------------------------------------------------- Hartmut · 2022-01-07 15:06 I tried both suggestions, thank you. Suggestion 1 did not help, but suggestion 2 did. Meanwhile I found out, that this "modal" problem is only on Linux Ubuntu 18.04, but not on Windows 7. I attached my little project and a screenshot of the Runtime-Error when pressing Button1. Are you on Windows or Linux? ---------------------------------------------------------------------- balazsszekely · 2022-01-07 15:36 @Hartmut QuoteI tried both suggestions, thank you. Suggestion 1 did not help, but suggestion 2 did. Meanwhile I found out, that this "modal" problem is only on Linux Ubuntu 18.04, but not on Windows 7. Windows and it works fine at my side, but should work with Linux(gtk2) too. In the past, there were some problem with modal forms(gtk2), but only when you show a modal form, from a modal form. Sort of a double modal form. As for the error message, you should set form2 visible property to false. ---------------------------------------------------------------------- Hartmut · 2022-01-07 18:01 OK, I think we've got it. I have a solution. Your posts and examples were easy to understand for me. Thanks a lot again for your help.