Il 27/03/23 09:46, Luca Olivetti via lazarus ha scritto:
Show quoted text 53 lines
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.