For-Schleife mit Ausgabe wie Diashow
-
- Beiträge: 9
- Registriert: Fr 6. Mär 2015, 09:07
For-Schleife mit Ausgabe wie Diashow
Hallo, ich habe folgendes Problem:
Für eine Anwendung möchte mir durch einem einfach ButtonClick 20 Würfelbilder NACHEINANDER anzeigen lassen (stark vereinfachtes Beispiel).
Das heißt, ich möchte einmal klicken und die Bilder sollen wie von Geisterhand nacheinander angezeigt werden (wie eine Diashow).
Ich würde nun gern wissen, wie ich das hinkriege.
Den Quellcode habe ich euch reingestellt (derzeit zeigt er einfach nur das letzte Bild; das kontrolliere ich nebenbei noch mit einer Variablenausgabe der Würfelaugenzahl, die ich hier nicht mit aufgeführt habe, da sie es nur unnötig komplizierter macht).
prcoedure TForm1.Button1Click(Sender: TObject);
begin
For Zaehler := 1 To 20 Do
begin
randomize;
sleep(150); [liefert andere Zufallszahlen]
wuerfel:=Random(6)+1;
case wuerfel of
1: Wuerfel1Image.Picture.LoadFromFile('\würfel1.png'); [Die Bilder sind jeweils Würfel mit der entsprechenden Augenzahl]
2: Wuerfel1Image.Picture.LoadFromFile('\würfel2.png');
3: Wuerfel1Image.Picture.LoadFromFile('\würfel3.png');
4: Wuerfel1Image.Picture.LoadFromFile('\würfel4.png');
5: Wuerfel1Image.Picture.LoadFromFile('\würfel5.png');
6: Wuerfel1Image.Picture.LoadFromFile('\würfel6.png');
end; end; end;
Vielen Dank im Voraus für eure Hilfe
Für eine Anwendung möchte mir durch einem einfach ButtonClick 20 Würfelbilder NACHEINANDER anzeigen lassen (stark vereinfachtes Beispiel).
Das heißt, ich möchte einmal klicken und die Bilder sollen wie von Geisterhand nacheinander angezeigt werden (wie eine Diashow).
Ich würde nun gern wissen, wie ich das hinkriege.
Den Quellcode habe ich euch reingestellt (derzeit zeigt er einfach nur das letzte Bild; das kontrolliere ich nebenbei noch mit einer Variablenausgabe der Würfelaugenzahl, die ich hier nicht mit aufgeführt habe, da sie es nur unnötig komplizierter macht).
prcoedure TForm1.Button1Click(Sender: TObject);
begin
For Zaehler := 1 To 20 Do
begin
randomize;
sleep(150); [liefert andere Zufallszahlen]
wuerfel:=Random(6)+1;
case wuerfel of
1: Wuerfel1Image.Picture.LoadFromFile('\würfel1.png'); [Die Bilder sind jeweils Würfel mit der entsprechenden Augenzahl]
2: Wuerfel1Image.Picture.LoadFromFile('\würfel2.png');
3: Wuerfel1Image.Picture.LoadFromFile('\würfel3.png');
4: Wuerfel1Image.Picture.LoadFromFile('\würfel4.png');
5: Wuerfel1Image.Picture.LoadFromFile('\würfel5.png');
6: Wuerfel1Image.Picture.LoadFromFile('\würfel6.png');
end; end; end;
Vielen Dank im Voraus für eure Hilfe
-
- Beiträge: 1910
- Registriert: Di 23. Sep 2014, 17:46
- OS, Lazarus, FPC: Win10 | Linux
- CPU-Target: x86_64
Re: For-Schleife mit Ausgabe wie Diashow
Ich würde dir an dieser Stelle empfehlen einen Timer zu machen.
Den Timer stellst du dann auf Enabled = False, und den Intervall auf die Länge, wie lang ein Bild angezeigt werden soll.
Den Timer stellst du dann auf Enabled = False, und den Intervall auf die Länge, wie lang ein Bild angezeigt werden soll.
Code: Alles auswählen
TForm1 = class(TForm)
...
private
FImageIndex: Integer;
...
end;
...
prcoedure TForm1.Button1Click(Sender: TObject);
begin
FImageIndex:=1;
ImageTimer.Enabled:=True;
end;
procedure TForm1.ImageTimerTimer(Sender: TObject);
ImageTimer.Enabled:=False;
Wuerfel1Image.Picture.LoadFromFile('\würfel'+IntToStr(Random(6)+1)+'.png');
inc(FImageIndex);
if FImageIndex = 20 then
begin
//Hier was Passieren soll nachdem alle Würfe durch sind
end
else
ImageTimer.Enabled:=True;
begin
end;
-
- 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: For-Schleife mit Ausgabe wie Diashow
InfoSchülerktog hat geschrieben:prcoedure TForm1.Button1Click(Sender: TObject);
begin
For Zaehler := 1 To 20 Do
begin
randomize;
sleep(150); [liefert andere Zufallszahlen]
....
Sorry. Aber darf man in Lazarus und ähnlichen Systemen nicht programnmieren !
"sleep" ist im Main-Thread nicht erlaubt, sondern nur in "Worker-Threads". (Thread-Programmieru8ng bekommen wir aber erst später...)
Der Main-Thread darf niemals auf irgendetwas warten.
Solche Systeme heißen "Event-orientiert". Da muss man jede Aktion als "Event" programmieren. Ein "Event" (in diesem Sinne) ist ein Unterprogramm, das vom System aufgerufen wird, irgendetwas macht, und dann wieder verlassen wird ("Run-To-Completion-Event").
Um Zeitgesteuerte Aktionen zu machen gibt es TTimer, der regelmäßig ein Event aufruft.
-Michael
Re: For-Schleife mit Ausgabe wie Diashow
mschnell hat geschrieben:Der Main-Thread darf niemals auf irgendetwas warten.
Seit wann? Wo steht das?
-
- Beiträge: 6194
- Registriert: Do 2. Jan 2014, 17:21
- OS, Lazarus, FPC: Linux (die neusten Trunk)
- CPU-Target: 64Bit
- Wohnort: Schweiz
Re: For-Schleife mit Ausgabe wie Diashow
Ich würde zumindest ein Application.ProcessMessages; einbauen, ansonsten kann das Programm nicht unterbrochen werden, bis die Schleife durch ist.
Beispiel:
Wie Warf schon schreibt, ein Timer ist eleganter.
Beispiel:
Code: Alles auswählen
var
Abbruch: boolean;
procedure TForm1.StopClick(Sender: TObject);
begin
Abbruch := True;
end;
procedure TForm1.StartClick(Sender: TObject);
begin
Abbruch := False;
repeat
Canvas.Pen.Color := Random($FFFFFF);
Canvas.LineTo(Random(ClientWidth), Random(ClientHeight));
sleep(100);
Application.ProcessMessages;
if Abbruch then Exit;
until 1 = 2;
end;
Wie Warf schon schreibt, ein Timer ist eleganter.
Mit Lazarus sehe ich grün
Mit Java und C/C++ sehe ich rot
Mit Java und C/C++ sehe ich rot
-
- Beiträge: 9
- Registriert: Fr 6. Mär 2015, 09:07
Re: For-Schleife mit Ausgabe wie Diashow
Also erstmal danke für die vielen Antworten.
@ warf, ich bekomme da ständig einen Compilerfehler in der "ImageTimer.Enabled:=True;"-Zeile, das scheint so nicht zu funktionieren.
External SIGSEGV - den Fehler hatte ich schon oftmals, lösen konnte ich ihn nur indem ich die Routinen umgehe (wobei ich hier leider nicht weiß wie).
Das liegt dann meist nicht am Programm an sich, sondern eben am LazarusCompiler der (Lazarus ist ja free) eben nicht so perfekt ist wie ein DelphiCompiler.
@ mschnell ich habe das Beispiel stark vereinfacht. diese procedure soll in Form9 ablaufen, ist also nicht in der MainForm. Das mit dem sleep funktioniert soweit ja auch super, nur klappt das mit der zeitversetzten Anzeige eben nicht.
Deshalb frage ich euch, ob ihr außer der Timer Variante die bei Lazarus offenbar nicht funktioniert noch eine andere Möglichkeit kennt? Danke
@ warf, ich bekomme da ständig einen Compilerfehler in der "ImageTimer.Enabled:=True;"-Zeile, das scheint so nicht zu funktionieren.
External SIGSEGV - den Fehler hatte ich schon oftmals, lösen konnte ich ihn nur indem ich die Routinen umgehe (wobei ich hier leider nicht weiß wie).
Das liegt dann meist nicht am Programm an sich, sondern eben am LazarusCompiler der (Lazarus ist ja free) eben nicht so perfekt ist wie ein DelphiCompiler.
@ mschnell ich habe das Beispiel stark vereinfacht. diese procedure soll in Form9 ablaufen, ist also nicht in der MainForm. Das mit dem sleep funktioniert soweit ja auch super, nur klappt das mit der zeitversetzten Anzeige eben nicht.
Deshalb frage ich euch, ob ihr außer der Timer Variante die bei Lazarus offenbar nicht funktioniert noch eine andere Möglichkeit kennt? Danke
Re: For-Schleife mit Ausgabe wie Diashow
InfoSchülerktog hat geschrieben: Das liegt dann meist nicht am Programm an sich, sondern eben am LazarusCompiler der (Lazarus ist ja free) eben nicht so perfekt ist wie ein DelphiCompiler.
Interessante These.
Also wenn ich gegen einen Baum fahre, ist das halt weil ich nur einen VW habe und keinen Audi?
-
- Beiträge: 1910
- Registriert: Di 23. Sep 2014, 17:46
- OS, Lazarus, FPC: Win10 | Linux
- CPU-Target: x86_64
Re: For-Schleife mit Ausgabe wie Diashow
InfoSchülerktog hat geschrieben:ich bekomme da ständig einen Compilerfehler in der "ImageTimer.Enabled:=True;"-Zeile, das scheint so nicht zu funktionieren.
External SIGSEGV - den Fehler hatte ich schon oftmals, lösen konnte ich ihn nur indem ich die Routinen umgehe (wobei ich hier leider nicht weiß wie).
Das liegt dann meist nicht am Programm an sich, sondern eben am LazarusCompiler der (Lazarus ist ja free) eben nicht so perfekt ist wie ein DelphiCompiler.
Grundsätzlich sind Delphi und FreePascal 2 unterschiedliche Sprachen, und ich muss sagen, ich finde den FPC weitaus besser als Delphi, die Probleme die du hast könnten aufgrund falsche Projekt Einstellungen zustande kommen.
-
- Beiträge: 9
- Registriert: Fr 6. Mär 2015, 09:07
Re: For-Schleife mit Ausgabe wie Diashow
Also das Problem ist, dass es auch nicht funktioniert, wenn ich den Debugger komplett ausschalte. Es muss also ein anderes Problem sein.
Der External: SIGSEGV kann ja vieles bedeuten, er zeigt mir halt direkt diese eine Zeile an, wo ich den Timer an bzw. ausschalte (das Programm läuft mit dem Timer schon super, nur kann ich ihn halt nicht stoppen, weshalb es sich logischer weise immer aufhängt^^).
Der External: SIGSEGV kann ja vieles bedeuten, er zeigt mir halt direkt diese eine Zeile an, wo ich den Timer an bzw. ausschalte (das Programm läuft mit dem Timer schon super, nur kann ich ihn halt nicht stoppen, weshalb es sich logischer weise immer aufhängt^^).
Re: For-Schleife mit Ausgabe wie Diashow
InfoSchülerktog hat geschrieben:Also das Problem ist, dass es auch nicht funktioniert, wenn ich den Debugger komplett ausschalte. Es muss also ein anderes Problem sein.
Der External: SIGSEGV kann ja vieles bedeuten, er zeigt mir halt direkt diese eine Zeile an, wo ich den Timer an bzw. ausschalte (das Programm läuft mit dem Timer schon super, nur kann ich ihn halt nicht stoppen, weshalb es sich logischer weise immer aufhängt^^).
Jetzt könnte ich die Glaskugel holen, oder du könntest deinen Code zeigen.
Was ist dir lieber?
-
- Beiträge: 6194
- Registriert: Do 2. Jan 2014, 17:21
- OS, Lazarus, FPC: Linux (die neusten Trunk)
- CPU-Target: 64Bit
- Wohnort: Schweiz
Re: For-Schleife mit Ausgabe wie Diashow
So sollte es klappen.
Code: Alles auswählen
var
Zaehler: integer;
FileList: TStringList;
procedure TForm1.Timer1Timer(Sender: TObject);
begin
Inc(Zaehler);
if Zaehler = 20 then begin
Timer1.Enabled := False;
end;
Image1.Picture.LoadFromFile(FileList[Random(FileList.Count)]);
end;
procedure TForm1.StartClick(Sender: TObject);
begin
Timer1.Enabled := True;
Zaehler := 0;
end;
procedure TForm1.FormCreate(Sender: TObject);
begin
FileList := FindAllFiles('.', '*.png;*.bmp', False);
end;
procedure TForm1.FormDestroy(Sender: TObject);
begin
FileList.Free;
end;
procedure TForm1.StopClick(Sender: TObject);
begin
Timer1.Enabled := False;
Image1.Picture.Clear;
end;
Mit Lazarus sehe ich grün
Mit Java und C/C++ sehe ich rot
Mit Java und C/C++ sehe ich rot
-
- 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: For-Schleife mit Ausgabe wie Diashow
InfoSchülerktog hat geschrieben:@ mschnell ich habe das Beispiel stark vereinfacht. diese procedure soll in Form9 ablaufen, ist also nicht in der MainForm.
Es geht nicht um "MainForm" sondern um "MainThread" (auch GUI-Thread genannt). Alle Forms werden vom Main (GUI)-Thread gemanaged. Und (nur) dieser Thread ist in Lazarus (wenn eine "Application" programmiert wird) dem "Event-Orientierten Programmieren" http://de.wikipedia.org/wiki/Ereignis_% ... mierung%29 und damit dem "Run-To-Completion" Paradigma unterworfen und darf deshalb nicht warten (potentiell lang-dauenrnde Schleife oder sleep).
Wenn man um die Grundlagen des verwendeten infrastruktur-Systems herumprogrammiert muss man mit unerwarteten Effekten rechen.InfoSchülerktog hat geschrieben:Das mit dem sleep funktioniert soweit ja auch super, nur klappt das mit der zeitversetzten Anzeige eben nicht.
Natürlich muss man nicht unbedingt eine Lararus Applikation machen. Z.B. ein "Kommandozeilen-Programm" wird von Lazarus nicht Ereignis-Orientiert angelegt.InfoSchülerktog hat geschrieben:Deshalb frage ich euch, ob ihr außer der Timer Variante die bei Lazarus offenbar nicht funktioniert noch eine andere Möglichkeit kennt? Danke
-Michael
-
- 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: For-Schleife mit Ausgabe wie Diashow
InfoSchülerktog hat geschrieben: Das liegt dann meist nicht am Programm an sich, sondern eben am LazarusCompiler der (Lazarus ist ja free) eben nicht so perfekt ist wie ein DelphiCompiler.
Völliger Unsinn !
Linux ist auch "Free" und eines der (unter Berücksichtihgung der Komplexität) zuverlässigsten, schnellsten und (als Basis von Android) weit verbreitetsten Betriebssysteme (also Programme) überhaupt.
-Michael
Re: For-Schleife mit Ausgabe wie Diashow
@mschnell: Könntest du mir die obige Frage bitte noch beantworten? Das ist neu für mich.
viewtopic.php?p=76026#p76026
Warum darf ein Main-Thread nicht 150 ms sleepen? Wo steht das? Was passiert dann?
viewtopic.php?p=76026#p76026
Warum darf ein Main-Thread nicht 150 ms sleepen? Wo steht das? Was passiert dann?
-
- Beiträge: 203
- Registriert: Di 22. Sep 2009, 13:08
- OS, Lazarus, FPC: Winux (L 0.9.xy FPC 2.2.z)
- CPU-Target: xxBit
Re: For-Schleife mit Ausgabe wie Diashow
theo hat geschrieben:
Warum darf ein Main-Thread nicht 150 ms sleepen? Wo steht das? Was passiert dann?
Passieren sollte nicht viel. Aber falls eine Anwendung im Hauptthread zu lange nicht reagiert bringt
Windows ein Popup und fragt den User, ob es die Anwendung killen soll. Sehr unschön sowas...
Unter Windows muss man praktisch in alles was im Main-Thread länger als eine Sekunde braucht
idiotischen "bitte bitte nicht killen"-Code für Windows einbauen.
Daher finde ich es schon verständlich wenn jemand so ein Sleep prinzipiell ablehnt.