[Lazarus] animated splash screen for lengthy operation, works with windows, doesn't with linux

Giuliano Colla giuliano.colla at fastwebnet.it
Mon Mar 27 12:07:07 CEST 2023


Il 27/03/23 09:46, Luca Olivetti via lazarus ha scritto:
> Hello,
>
> I'd like to show a splash screen with an animation during a lengthy 
> operation.
> I cannot rely on a timer to show the animation since the message loop 
> isn't running, so I'm using a thread to directly paint over the form, 
> i.e.:
>
>
> WaitForm.Show;
> Application.ProcessMessages;
>
> ...
>
> procedure TWaitForm.FormShow(Sender: TObject);
> begin
>   FUpdateThread:=TUpdateThread.Create(self);
> end;
>
> ...
>
> procedure TUpdateThread.Execute;
> begin
>   while not Terminated do
>   begin
>     FWaitForm.ShowProgress;
>     Sleep(30);
>   end;
> end;
>
> ...
>
> procedure TWaitForm.ShowProgress;
> begin
>   PaintBox1.Canvas.Clear;
>   //WaitAnimation is an image list
>   WaitAnimation.Draw(PaintBox1.Canvas,0,0,FImageIndex);
>   FImageIndex:=FImageIndex+1;
>   if FImageIndex>=WaitAnimation.Count then
>     FImageIndex:=0;
> end;
>
>
> This works wonderfully under windows (which is my intended target, so 
> no problem here), but under Linux it doesn't work (tested with gtk2, 
> gtk3 and qt5). In fact, even the "Show; Application.ProcessMessages" 
> is erratic, sometimes it shows the form, sometimes it doesn't.
>
> Lazarus 2.2.6/fpc 3.2.2
>
> Any idea?
>
> Bye


Yes, it's a known issue.

The difference between Windows and Unix is that Windows generates 
frequently useless mouse events to all windows, which wake up the main 
thread of Delphi/Lazarus, while Unix/X11/Wayland is well behaved and 
sends a mouse event only to the appropriate window, and only if there's 
been a physical mouse event to send.

You may verify if such is the case by moving the mouse over your splash 
screen window. You move the mouse and the image is updated, you stop 
moving and the image freezes.

In a similar scenario my solution has been that of an horrible hack. 
It's a hack, but it works. I've put in a corner of my window a label of 
just one character, and, with a frequent timer (200 ms in my case) I 
update the caption. I'm using a sequence of "-" "\" " |" "/" "-" to 
display a rotating bar. Usually users do not even notice, but if they do 
it's harmless. This way I trigger an event which will force a paint 
operation, and all pending graphic updates are performed.

Maybe this works also for you. You should just tune the timer to the 
speed of your animation.

Hope that it helps,

Giuliano

-- 
Do not do to others as you would have them do to you.They might have different tastes.



More information about the lazarus mailing list