Recent

Author Topic: [SOLVED] How to switch a Form from Show-mode to ShowModal() without flicker?  (Read 2550 times)

Hartmut

  • Hero Member
  • *****
  • Posts: 532
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][+][-]
  1. // Extract from Unit1:
  2. procedure TForm1.Button1Click(Sender: TObject);
  3.    begin
  4.    Form2.display_Infos;
  5.    end;
  6.  
  7. // Extract from Unit2:
  8. procedure TForm2.display_Infos;
  9.    begin
  10.    Memo1.Clear;
  11.    Memo1.Lines.Add('This are Infos part 1');
  12.    Show; {display Infos part 1}
  13.    Application.ProcessMessages; {neccessary to display Infos part 1}
  14.  
  15.    sleep(2000); {simulates gathering Infos part 2}
  16.  
  17.    Memo1.Lines.Add('This are Infos part 2');
  18.    Hide; {is neccessary before ShowModal()}
  19.    ShowModal; {a flicker occurs between Hide() and ShowModal()}
  20.    end;
  21.  
  22. procedure TForm2.Button_ActionClick(Sender: TObject);
  23.    begin
  24.    // do some actions...
  25.    Close;
  26.    end;
  27.  
  28. procedure TForm2.Button_CloseClick(Sender: TObject);
  29.    begin
  30.    Close;
  31.    end;  
« Last Edit: January 07, 2022, 07:02:06 pm by Hartmut »

GetMem

  • Hero Member
  • *****
  • Posts: 3752
Re: How to switch a Form from Show-mode to ShowModal() without flicker?
« Reply #1 on: January 07, 2022, 12:16:12 pm »
@Hartmut

Show the form with FormX.ShowModal, then on FormShow event start a timer, like this:
Code: Pascal  [Select][+][-]
  1. procedure TFormX.FormShow(Sender: TObject);
  2. begin
  3.   Timer1.Interval := 300;
  4.   Timer1.Enabled := True;
  5. end;
  6.  
  7. procedure TFormX.Timer1Timer(Sender: TObject);
  8. begin
  9.   Timer1.Enabled := False;
  10.   Memo1.Clear;
  11.   Memo1.Lines.Add('This are Infos part 1');
  12.  
  13.   Self.Enabled := False; //prevent user to close form
  14.   try
  15.     //do lengthy process here
  16.     Memo1.Lines.Add('This are Infos part 2');
  17.   finally
  18.     Self.Enabled := True;
  19.   end;
  20. end;  

PS: On design time set Timer1.Enabled to false.

Hartmut

  • Hero Member
  • *****
  • Posts: 532
Re: How to switch a Form from Show-mode to ShowModal() without flicker?
« Reply #2 on: January 07, 2022, 01:14:16 pm »
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.

GetMem

  • Hero Member
  • *****
  • Posts: 3752
Re: How to switch a Form from Show-mode to ShowModal() without flicker?
« Reply #3 on: January 07, 2022, 02:14:03 pm »
@Hartmut
Quote
Thanks a lot GetMem for your quick reply.
You are welcome!

Quote
Before 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

  • Hero Member
  • *****
  • Posts: 532
Re: How to switch a Form from Show-mode to ShowModal() without flicker?
« Reply #4 on: January 07, 2022, 02:52:52 pm »
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][+][-]
  1. procedure TForm2.display_Infos;
  2.    begin
  3.    ShowModal; {calls FormShow()}
  4.    end;
  5.  
  6. procedure TForm2.FormShow(Sender: TObject);
  7.    {Event "OnShow"}
  8.    begin
  9.    writeln('OnShow - start Timer');
  10.    Timer1.Interval := 300; {in ms}
  11.    Timer1.Enabled := True;
  12.    end;
  13.  
  14. procedure TForm2.Timer1Timer(Sender: TObject);
  15.    {Event "OnTimer" des Timers}
  16.    begin
  17.    Timer1.Enabled := False;
  18.    writeln('Timer1Timer');
  19.  
  20.    Memo1.Clear;
  21.    Memo1.Lines.Add('This are Infos part 1');
  22.    Application.ProcessMessages; {neccessary to display Infos part 1}
  23.  
  24.    Self.Enabled := False; // prevent user to close form
  25.    try //do lengthy process here:
  26.        sleep(2000); {simulates gathering Infos part 2}
  27.        Memo1.Lines.Add('This are Infos part 2');
  28.    finally
  29.        Self.Enabled := True;
  30.    end; {try}
  31.    end;

Did I made something wrong?

GetMem

  • Hero Member
  • *****
  • Posts: 3752
Re: How to switch a Form from Show-mode to ShowModal() without flicker?
« Reply #5 on: January 07, 2022, 03:04:46 pm »
Quote
Did 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][+][-]
  1. procedure TForm1.Button1Click(Sender: TObject);
  2. begin
  3.   Form2.ShowModal;
  4. end;
  5.  
If your second form(Form2) does not behave like a modal form, please attach your project or try something like this:
Code: Pascal  [Select][+][-]
  1. procedure TForm1.Button1Click(Sender: TObject);
  2. begin
  3.   Form1.Enabled := False;
  4.   try
  5.     Form2.ShowModal;
  6.   finally
  7.     Form1.Enabled := True;
  8.   end;
  9. end;
The last method really shouldn't be necessary.  ShowModal always works fine for me.

Hartmut

  • Hero Member
  • *****
  • Posts: 532
Re: How to switch a Form from Show-mode to ShowModal() without flicker?
« Reply #6 on: January 07, 2022, 04:06:37 pm »
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?

GetMem

  • Hero Member
  • *****
  • Posts: 3752
Re: How to switch a Form from Show-mode to ShowModal() without flicker?
« Reply #7 on: January 07, 2022, 04:36:52 pm »
@Hartmut
Quote
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.
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

  • Hero Member
  • *****
  • Posts: 532
Re: How to switch a Form from Show-mode to ShowModal() without flicker?
« Reply #8 on: January 07, 2022, 07:01:38 pm »
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.

 

TinyPortal © 2005-2018