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.

--
_______________________________________________
lazarus mailing list
lazarus@lists.lazarus-ide.org
https://lists.lazarus-ide.org/listinfo/lazarus

Reply via email to