Formular mit Bild kurz aufblenden, Windows gut, Linux nicht

Antworten
Der Proband
Beiträge: 7
Registriert: Di 24. Mai 2016, 09:47

Formular mit Bild kurz aufblenden, Windows gut, Linux nicht

Beitrag von Der Proband »

Hallo,
ich programmiere schon länger mit Pascal, aber noch nicht lange mit Lazarus. Jetzt hänge ich an einem Problem, bei dem ich nicht mehr weiter komme. Auch Google hat mir bisher noch nicht geholfen.
Die Aufgabe ist, auf das eigentlich Problem heruntergebrochen, einfach zu beschreiben: Bei Drücken eines Buttons im Hauptformular soll sich ein zweites Formular öffnen und ein Bild anzeigen. Nach einer gewissen Zeit soll sich das Formular wieder schließen. Umgestzt habe ich das wie folgt:

Code: Alles auswählen

procedure TForm1.Button1Click(Sender: TObject);
begin
   form2.show;
   form2.Image1.Picture.LoadFromFile('Test.jpg');
   form2.refresh;
   sleep(3000);
   form2.hide;
end;


Das Ganze funktioniert unter Windows wie es soll. Auf dem raspberry PI mit raspbian Jessie geht das Fenster auf, enthält aber kein Bild. Lasse ich sleep und hide weg, wird das Bild dargestellt, aber natürlich bleibt das Fenster offen. Die Darstellung des Bildes ist also nicht das Problem, wohl eher der sleep Befehl. Wie kann man das Problem umgehen und was ist die Ursache für das Unterschiedliche Verhalten unter Windows und Linux?
Zuletzt geändert von Lori am Di 24. Mai 2016, 19:25, insgesamt 1-mal geändert.
Grund: Highlighter

Benutzeravatar
theo
Beiträge: 10467
Registriert: Mo 11. Sep 2006, 19:01

Re: Formular mit Bild kurz aufblenden, Windows gut, Linux ni

Beitrag von theo »

Sleep ist nicht so das Wahre in der GUI Programmierung. Nimm lieber einen TTimer.

FXMaveric
Beiträge: 19
Registriert: Mi 7. Jan 2009, 08:59

Re: Formular mit Bild kurz aufblenden, Windows gut, Linux ni

Beitrag von FXMaveric »

theo hat recht.

Kurz: sleep hält den GUI-Threadoder MainThread an, in dem auch die grafische Anzeige abläuft.
Das Show und Refresh löst ein Invalidate aus, welches asynchron abgearbeitet wird. Es kommt also gar nicht zu Anzeige bevor du das Fenster schließt, da der Anzeigethread ja Pause macht.
Mit einem Timer sollte es keine Probleme geben.

Gruß
FX

Komoluna
Beiträge: 565
Registriert: So 26. Aug 2012, 09:03
OS, Lazarus, FPC: Windows(10), Linux(Arch)
CPU-Target: 64Bit

Re: Formular mit Bild kurz aufblenden, Windows gut, Linux ni

Beitrag von Komoluna »

Mich wunderts eher, dass es unter Windows trotzdem klappt.

MFG

Komoluna
Programmer: A device to convert coffee into software.

Rekursion: siehe Rekursion.

SoE
Beiträge: 84
Registriert: Mo 31. Aug 2015, 01:51

Re: Formular mit Bild kurz aufblenden, Windows gut, Linux ni

Beitrag von SoE »

Versuch mal

Code: Alles auswählen

Form2.Update;
vor dem Sleep.

Ich benutze bei einem selbstgebauten Button oft "Sleep" um das zweite PNG beim "MouseDown" anzuzeigen und ohne

Code: Alles auswählen

FormXYZ.Update
funzt das nicht.

Code: Alles auswählen

 
 form2.Image1.Picture.LoadFromFile('Test.jpg');
 form2.show;
 form2.Update;
 sleep(3000);
 form2.hide;
 


Willst du nicht lieber erst beim Klick auf den Button das Fenster erstellen lassen?
Oder dauert das zu lange? Das Bild könnte man auch in "FormCreate" laden lassen... (FormCreate des Hauptfensters)

Code: Alles auswählen

 
Procedure TForm1.Button1Click(Sender: TObject);
  Var
   Info: TForm;
   Pic : TImage;
 Begin
  Try
   Info         := TForm.Create(Nil);
   Info.Position:= poScreenCenter;
   Info.Height  := 300;
   Info.Width   := 300;
 
   Pic       := TImage.Create(Nil);
   Pic.Align := alClient;
   Pic.Parent:= Info;
   Pic.Picture.LoadFromFile('I:\(DOWNLOADS)\Logo.png');
 
   Info.Show;
   Info.Update;
   Sleep(3000);
  Finally
   FreeAndNil(Pic);
   Info.Release;
   Info:= Nil;
  End;
 End;     
 


Wenn man in den 3 Sekunden mit dem Hauptfenster etwas machen soll, dann wäre natürlich wie schon von den anderen erwähnt ein Timer 'ne gute Idee...

SoE
Beiträge: 84
Registriert: Mo 31. Aug 2015, 01:51

Re: Formular mit Bild kurz aufblenden, Windows gut, Linux ni

Beitrag von SoE »

Mit Timer könnte man es so machen...
Vielleicht gibt es auch noch 'ne bessere Lösung...

Code: Alles auswählen

 
Unit uForm2;
 {$mode objfpc}{$H+}
Interface
 Uses
  Classes, SysUtils, FileUtil, Forms, Controls, Graphics, StdCtrls, ExtCtrls;
 
 Type
  TForm1 = Class(TForm)
   Button1: TButton;
 
    Procedure Button1Click(Sender: TObject);
    Procedure SleepTimer  (Sender: TObject);
  End;
 
 VAR
  Form1: TForm1;
 
Implementation
 {$R *.lfm}
 
 
Procedure TForm1.Button1Click(Sender: TObject);
  Var
   Info: TForm;
   Pic : TImage;
   Ti  : TTimer;
 Begin
  Info         := TForm.Create(Nil);
  Info.Position:= poScreenCenter;
  Info.Height  := 300;
  Info.Width   := 300;
 
  Pic       := TImage.Create(Info);
  Pic.Align := alClient;
  Pic.Parent:= Info;
  Pic.Picture.LoadFromFile('I:\(DOWNLOADS)\Logo.png');
 
  Ti         := TTimer.Create(Info);
  Ti.Interval:= 3000;
  Ti.Enabled := False;
  Ti.OnTimer := @SleepTimer;
 
  Info.Show;
  //ohne Update;
  Ti.Enabled:=True;
 End;
 
 
Procedure TForm1.SleepTimer(Sender: TObject);
 Begin
  TTimer(Sender).Enabled:= False;
  TTimer(Sender).Owner.Free;
 End;
 
End.                       
 

FXMaveric
Beiträge: 19
Registriert: Mi 7. Jan 2009, 08:59

Re: Formular mit Bild kurz aufblenden, Windows gut, Linux ni

Beitrag von FXMaveric »

Das es unter Windows klappt (klappen kann), hängt mit der anderen Nachrichtenkettenimplementation und dem Timing zusammen.
Linux hat von Haus aus keine Nachrichtenkette/Messsages wie Windows und wird quasi von FPC emuliert.

mschnell
Beiträge: 3444
Registriert: Mo 11. Sep 2006, 10:24
OS, Lazarus, FPC: svn (Window32, Linux x64, Linux ARM (QNAP) (cross+nativ)
CPU-Target: X32 / X64 / ARMv5
Wohnort: Krefeld

Re: Formular mit Bild kurz aufblenden, Windows gut, Linux ni

Beitrag von mschnell »

theo hat geschrieben:Sleep ist nicht so das Wahre in der GUI Programmierung.


+1

Ich würde es allerdings härter ausdrücken: Sleep ist im Main-Thread verboten, egal welches Betriebssystem.

-Michael

Requion
Beiträge: 106
Registriert: Mi 3. Feb 2016, 09:39
OS, Lazarus, FPC: Linux(Arch Linux(+ARM)/Minibian) (L 1.6.0 FPC 3.0.0)
CPU-Target: 32/64Bit,ARM(RPi)
Wohnort: nahe Grimma

Re: Formular mit Bild kurz aufblenden, Windows gut, Linux ni

Beitrag von Requion »

mschnell hat geschrieben:
theo hat geschrieben:Sleep ist nicht so das Wahre in der GUI Programmierung.


+1

Ich würde es allerdings härter ausdrücken: Sleep ist im Main-Thread verboten, egal welches Betriebssystem.

-Michael

Ach warum denn so hart? Ist doch toll wenn der Nutzer immer mal Pause machen kann weil das Programm hängt :D *Ironie aus*.
Mfg Requion

Das beste an Standards ist, dass es so viele davon gibt.

SoE
Beiträge: 84
Registriert: Mo 31. Aug 2015, 01:51

Re: Formular mit Bild kurz aufblenden, Windows gut, Linux ni

Beitrag von SoE »

Vielleicht sollte man das Laden besser so machen:
Oder du lädst das Bild aus einer Ressource...

Code: Alles auswählen

 
  Pic       := TImage.Create(Info);
  Pic.Align := alClient;
  Pic.Parent:= Info;
 
   If FileExists('I:\(DOWNLOADS)\Logo.png')
   Then
    Begin
     Try
      Pic.Picture.LoadFromFile('I:\(DOWNLOADS)\Logo.png');
     Except
      On E: Exception
      Do
       Begin
        // Fenster anzeigen oder nur ein ErrorLog, sollte zu deinem restlichen
        // Exception-Handling passen...
        // nach deinem Text vielleicht noch: E.ClassName+#13#10+E.Message
       End;
     End;
    End;     
 


by the way:

Vielleicht kennst du das ja schon, ist sehr praktisch:
Wenn du im Menü auf "Projekt", "Projekteinstellungen" gehst und dann auf "Pfade" klickst (unter Compilereinstellungen), dann kannst du in der ersten Zeile (Erstellmodi) auf den Button mit den drei Punkten klicken und in dem sich öffnenden Fenster den Button "Debug- und Release-Modi erstellen" klicken. Danach wird automatisch der Debug-Modus ausgewählt und es erscheint ein neuer kleiner Button links neben dem Compilieren(Start)-Button in der Schnellstartleiste.

Wenn du jetzt auf Start(Compilieren) drückst wird nach der Programmausführung ein Error-Dialog angezeigt, der dir in der vierten Zeile "unfreed memory blocks: .." anzeigt. Damit kann man schön sehen ob auch alles wieder freigegeben wurde. Ob das auch funktioniert wenn man direkt über die API Speicher reserviert hab' ich noch nicht ausprobiert...

Und wenn du den Modus auf "Release" stellst, hast du eine viel kleinere Echse ohne die DebugInformationen.

Der Proband
Beiträge: 7
Registriert: Di 24. Mai 2016, 09:47

Re: Formular mit Bild kurz aufblenden, Windows gut, Linux ni

Beitrag von Der Proband »

Hallo,
ich bedanke mich schonmal für das schnelle und umfangreiche feedback. In den nächsten Tagen werde ich das ausprobieren und mich wieder, vielleicht auch mit Fragen, melden. Die eigentliche Aufgabe war ein Webcambild mittels Synapse zu laden und anschließend kurzzeitig anzuzeigen und kein Bild aus einer lokal gespeicherten Datei. Das Problem mit dem Sleep war jedoch bei beiden Aufgaben das gleiche und ich denke, die Lösung wird auch bei dem anderen Anwedungsfall, der vielleicht etwas komplexer ist, funtionieren.
Nochmals vielen Dank.

SoE
Beiträge: 84
Registriert: Mo 31. Aug 2015, 01:51

Re: Formular mit Bild kurz aufblenden, Windows gut, Linux ni

Beitrag von SoE »

Das Einfachste und Beste wäre wahrscheinlich das hier:

Code: Alles auswählen

 
Unit uForm2;
 {$mode objfpc}{$H+}
Interface
 Uses
  Classes, SysUtils, FileUtil, Forms, Controls, Graphics, StdCtrls, ExtCtrls;
 
 Type
  TForm1 = Class(TForm)
 
   Button1: TButton;
 
    Procedure Button1Click (Sender: TObject);
    Procedure CloseClick   (Sender: TObject;  Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
  End;
 
 VAR
  Form1: TForm1;
 
Implementation
 {$R *.lfm}
 
 
Procedure TForm1.Button1Click(Sender: TObject);
  Var
   Info: TForm;
   Pic : TImage;
 Begin
  Info         := TForm.Create(Nil);
  Info.Position:= poScreenCenter;
  Info.Height  := 300;
  Info.Width   := 300;
 
  Pic          := TImage.Create(Info);
  Pic.Align    := alClient;
  Pic.Parent   := Info;
  Pic.OnMouseUp:= @CloseClick;
  Pic.Picture.LoadFromFile('I:\(DOWNLOADS)\Logo.png');
 
  Info.Show;
 End;
 
 
Procedure TForm1.CloseClick(Sender: TObject; Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
 Begin
  If Button = mbRight
  Then TImage(Sender).Owner.Free;
 End;
 
 
End.           
 


Wenn etwas angezeigt werden soll, dann kann man davon ausgehen, dass jemand das Angezeigte sehen soll und dann hat dieser Jemand vielleicht ja sogar eine Möglichkeit an dieser Stelle mit dem Programm zu interagieren. Daraus ergibt sich dann, dass es möglicherweise besser ist auf das ZeitIntervall zu verzichten, da dann jeder Nutzer selber festlegen kann wann er das Fenster schließen möchte.
Das Intervall würde bei Nutzerinteraktion nur dazu führen, dass ein Nutzer sagt "...zu kurz..." und ein anderer sagt "...zu lang..." und das könnte man einfach von vornherein umgehen...

Ist nur so ein Gedanke... :-)

Antworten