Autor Beitrag
nn1234
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 41

WIN XP
Delphi 7
BeitragVerfasst: Fr 30.12.05 10:48 
Hi!
Habe einen Timer gesetzt, der einige Dinge, gleich nach dem Aufruf des Formulars erledigen soll, unter anderem Bitmaps laden, da das mit Fomcreate ja nicht functioniert (ok, der war schlecht... :lol: ) Wollte jetzt mal fragen, ob es sein kann, dass der Timer zu viele Aktionen beinhaltet, sodass er, wenn ich die Eigenschaft Enable nach Erledigung der Aktionen auf False setze, gar nichts mehr macht? Hier mal der Quelltext:
ausblenden volle Höhe Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
27:
28:
29:
30:
31:
32:
33:
34:
35:
36:
37:
procedure TfKampf.Timer1Timer(Sender: TObject);
var level_Spieler,level_Gegner : Integer;art_Gegner,art_Spieler : String;
begin
  //Mittelpunkt setzen
  SetViewPortOrgEx(Canvas.Handle,fKampf.width DIV 2,fKampf.height DIV 2,nil);

  //Variablen Wert zuordnen
  if fAnfang.RadioGroup1.ItemIndex = 0 then
    art_Spieler := 'Eis';
  if FAnfang.RadioGroup2.ItemIndex = 0 then
    art_Gegner := 'Erde';
  level_Spieler := 1;
  level_Gegner := 1;
  life_max_Spieler := TKreatur.create(level_Spieler,art_Spieler);
  life_max_Gegner := TKreatur.create(level_Gegner,art_Gegner);

  //Kreraturenwahl des Spielers
  if fAnfang.RadioGroup1.ItemIndex = 0 then
  begin
    uNuetzlich.kreatur_zeichnen(fKampf.Canvas,'Kreaturen/Eiselement.Bmp',-330,-70);
    Label5.Caption := 'Eiselement';
    uNuetzlich.life_balken(fKampf.Canvas,life_max_Spieler.life_max,life_max_Spieler.life_max,1);
    Label6.Caption := IntToStr(life_max_Spieler.life_max);
    Label7.Caption := IntToStr(life_akt_Spieler);
    Label10.Caption := IntToStr(level_Spieler);
  end;

  //Kreaturenwahl des Gegners
  if fAnfang.RadioGroup2.ItemIndex = 0 then
  begin
    uNuetzlich.kreatur_zeichnen(fKampf.Canvas,'Kreaturen/Erdelement.Bmp',120,-280);
    Label4.Caption := 'Erdelement';
    uNuetzlich.life_balken(fKampf.Canvas,life_max_Gegner.life_max,life_max_Gegner.life_max,2);
    Label9.Caption := IntToStr(level_Gegner);
  end;

end;

Wenn ich jetzt ganz am Schluss Enable auf False setze, macht er gar nichts mehr. Das Intervall hab ich auf 100 gesetzt, hab's aber auch schon mit anderen Intervallen versucht.
nn
Narses
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Administrator
Beiträge: 10183
Erhaltene Danke: 1256

W10ent
TP3 .. D7pro .. D10.2CE
BeitragVerfasst: Fr 30.12.05 10:54 
Moin!

Alternative: FormShow und ein globales Flag; spart den Timer. :wink:

cu
Narses
nn1234 Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 41

WIN XP
Delphi 7
BeitragVerfasst: Fr 30.12.05 11:04 
...Hab keine Ahnung, was flags sind, und wie ich die anwende... :oops:
nn
Narses
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Administrator
Beiträge: 10183
Erhaltene Danke: 1256

W10ent
TP3 .. D7pro .. D10.2CE
BeitragVerfasst: Fr 30.12.05 11:17 
Moin!

Aaalso... :wink: Du machst die ganzen Aktionen im Ereignis FormShow(). Da du nicht ausschließen kannst, dass das Ereignis mehrfach auftritt, du aber nur das erste Auftreten bearbeiten willst, mußt du dir in einer globalen Variable vom Typ Boolean (z.B.) merken, dass du das schon getan hast. Konkret: gloablen Boolean anlegen und im FormCreate() auf FALSE setzen, im FormShow() nach allen Aktionen auf TRUE und die Aktionen per IF-THEN kapseln.

Auf diese Weise eingesetzte Bools nennt man auch schon mal Flag ("Signalfähnchen" so ganz grob).

cu
Narses
Gausi
ontopic starontopic starontopic starontopic starontopic starontopic starofftopic starofftopic star
Beiträge: 8553
Erhaltene Danke: 479

Windows 7, Windows 10
D7 PE, Delphi XE3 Prof, Delphi 10.3 CE
BeitragVerfasst: Fr 30.12.05 11:21 
Da ist wohl so etwas gemeint
ausblenden Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
var Erledigt: Boolean;

//im OnCreate:
Erledigt := False;

// im OnShow:
if Not Erledigt then
begin
  //Mach dies und das 
  //(halt der ganze Krempel, der zur Zeit im OnTimer steht)
  Erledigt := True;
end;

Sinn: Eine Boolsche Variable, die steuert, ob etwas ausgeführt werden soll, oder nicht. Nach einmaliger Ausführung wird diese Variable so gesetzt, dass das ganze nicht nochmal ausgeführt wird.

Edit: Hab ich wirklich 4 Minuten zum Tippen gebraucht...:gruebel:?

_________________
We are, we were and will not be.
wdbee
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 628
Erhaltene Danke: 1



BeitragVerfasst: Fr 30.12.05 11:25 
Das, was du im Timer-Event machst, soll doch nur ein einziges mal ausgeführt werden.
Im FormCreate-Ereignis geht es nicht, wie du sagst. Im FormShow-Ereignis geht es aber. Nur wird dieses Ereignis ggf. mehr als einmal auftreten, anders als FormCreate.
Deshalb musst du dir einfach merken, ob die Objekte, die du da erzeugen willst, schon erzeugt sind oder nicht.
Die Variable life_max_Spieler z.B. sollte nil sein, wenn es das Objekt noch nicht gibt.
Also kannst du einfach abfragen ob life_max_Spieler noch nil ist und nur dann die Initialisierung im FormShow-Ereignis ausführen. Damit verwendest du diese Variable als Flag (Flagge). Flagge oben = Objekt gibt es schon, Flagge unten = Objekt gibt es noch nicht. Ein Flag ist also eine Boolsche-Variable, die als Merker für etwas eingesetzt wird.

Die Verwendung von Timern für soetwas, hat den Nachteil, dass du nicht mehr sicher weißt, wann im Ablauf die Initialisierung ausgeführt wird! Wenn du dennoch einen Timer verwendest, um ein einmaliges Ereignis auszulösen, dann solltest du als erstes im TimerEvent Enabled auf false setzten, dann spielt es keine Rolle mehr, wie lange die Ausführung tatsächlich dauert.
nn1234 Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 41

WIN XP
Delphi 7
BeitragVerfasst: Fr 30.12.05 13:37 
Ist mit OnShow die Methode Form2.Show gemeint? Das Ereignis OnShow im Objektinspektor unter Ereignisse lässt sich nicht als Prozedur öffnen... :?
nn
Ja-Pa
ontopic starontopic starontopic starontopic starhalf ontopic starofftopic starofftopic starofftopic star
Beiträge: 458

Win XP, Suse 9.3
D1, D3, D5 Std, D7 Pro, D2005 Pers, Kylix 3
BeitragVerfasst: Fr 30.12.05 13:44 
Genau, Delphi benennt die Ereignisprozeduren immer so (aus Button1.OnClick wird Button1Click).
Kannst sie aber natürlich auch beliebig umbenennen wenn dich das stört :wink:

_________________
Der Autor dieses Textes haftet nicht für Schäden an Soft- oder Hardware
oder Vermögensschäden, die durch das Benutzen des Textes entstehen.
nn1234 Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 41

WIN XP
Delphi 7
BeitragVerfasst: Fr 30.12.05 13:45 
ausblenden volle Höhe Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
27:
28:
29:
30:
31:
32:
33:
34:
35:
36:
37:
38:
39:
40:
41:
42:
43:
44:
45:
46:
47:
48:
49:
50:
51:
var Erledigt : Boolean;
...
procedure TfKampf.FormCreate(Sender: TObject);
begin
  Erledigt := False;
end;

procedure TfKampf.FormShow(Sender: TObject);
var level_Spieler,level_Gegner : Integer;art_Gegner,art_Spieler : String;
begin
  if not Erledigt then
  begin

    //Mittelpunkt setzen
    SetViewPortOrgEx(Canvas.Handle,fKampf.width DIV 2,fKampf.height DIV 2,nil);

    //Variablen Wert zuordnen
    if fAnfang.RadioGroup1.ItemIndex = 0 then
      art_Spieler := 'Eis';
    if FAnfang.RadioGroup2.ItemIndex = 0 then
      art_Gegner := 'Erde';
    level_Spieler := 1;
    level_Gegner := 1;
    life_max_Spieler := TKreatur.create(level_Spieler,art_Spieler);
    life_max_Gegner := TKreatur.create(level_Gegner,art_Gegner);

    //Kreraturenwahl des Spielers
    if fAnfang.RadioGroup1.ItemIndex = 0 then
    begin
      uNuetzlich.kreatur_zeichnen(fKampf.Canvas,'Kreaturen/Eiselement.Bmp',-330,-70);
      Label5.Caption := 'Eiselement';
      uNuetzlich.life_balken(fKampf.Canvas,life_max_Spieler.life_max,life_max_Spieler.life_max,1);
      Label6.Caption := IntToStr(life_max_Spieler.life_max);
      Label7.Caption := IntToStr(life_akt_Spieler);
      Label10.Caption := IntToStr(level_Spieler);
    end;

    //Kreaturenwahl des Gegners
    if fAnfang.RadioGroup2.ItemIndex = 0 then
    begin
      uNuetzlich.kreatur_zeichnen(fKampf.Canvas,'Kreaturen/Erdelement.Bmp',120,-280);
      Label4.Caption := 'Erdelement';
      uNuetzlich.life_balken(fKampf.Canvas,life_max_Gegner.life_max,life_max_Gegner.life_max,2);
      Label9.Caption := IntToStr(level_Gegner);
    end;

    //Erledigt
    Erledigt := True;
  end;

end;

Funzt nicht, genau, wie wenn ich den Timer drin hab... :?
nn
Ja-Pa
ontopic starontopic starontopic starontopic starhalf ontopic starofftopic starofftopic starofftopic star
Beiträge: 458

Win XP, Suse 9.3
D1, D3, D5 Std, D7 Pro, D2005 Pers, Kylix 3
BeitragVerfasst: Fr 30.12.05 13:50 
user profile iconnn1234 hat folgendes geschrieben:
Funzt nicht


WAS funktioniert denn nicht? Fehlermeldung? Programm hängt? Schleife bricht vorzeitig ab?
Tipp: Einfach mal den Debugger drüber laufen lassen (im Einzelschritt ausführen -> mehrmals F7 drücken).
So kannst du die einzelnen Schritte genau nachvollziehen und siehst, wenn etwas nicht stimmt.

_________________
Der Autor dieses Textes haftet nicht für Schäden an Soft- oder Hardware
oder Vermögensschäden, die durch das Benutzen des Textes entstehen.
nn1234 Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 41

WIN XP
Delphi 7
BeitragVerfasst: Fr 30.12.05 13:54 
Fehlermeldung kommt keine, aber es werden keine Aktionen ausgeführt...
Zitat:
Funzt nicht, genau, wie wenn ich den Timer drin hab...

siehe weiter oben:
Zitat:
...macht er gar nichts mehr
Ja-Pa
ontopic starontopic starontopic starontopic starhalf ontopic starofftopic starofftopic starofftopic star
Beiträge: 458

Win XP, Suse 9.3
D1, D3, D5 Std, D7 Pro, D2005 Pers, Kylix 3
BeitragVerfasst: Fr 30.12.05 13:58 
Meinst du mit gar nichts mehr, dass sich das Programm "aufhängt"?
Dann würd ich mal die Prozeduren im OnCreate-Ereignis (z.B. SetViewPortOrgEx) überprüfen... sonst müsste der Code IMHO funktionieren :?

_________________
Der Autor dieses Textes haftet nicht für Schäden an Soft- oder Hardware
oder Vermögensschäden, die durch das Benutzen des Textes entstehen.
nn1234 Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 41

WIN XP
Delphi 7
BeitragVerfasst: Fr 30.12.05 14:06 
Nein, die Aktionen, die im OnShow stehen, werden einfach nicht ausgefährt.
Narses
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Administrator
Beiträge: 10183
Erhaltene Danke: 1256

W10ent
TP3 .. D7pro .. D10.2CE
BeitragVerfasst: Fr 30.12.05 14:16 
Moin!

Pack mal ein ShowMessage('Hallo'); mit rein, dann starten. Kommt was?

cu
Narses
nn1234 Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 41

WIN XP
Delphi 7
BeitragVerfasst: Fr 30.12.05 17:30 
Unerwarteter Weise ja. Bevor Form2 sichtbar ist, zeigt's mir 'Hallo'. Kann es also sein, das die Aktionen zwar ausgeführt werden, dies allerdings zu früh und dass man sie darum nicht ausgeführt sieht? Wenn ja, wie behebt man solch ein Problem?
DarkHunter
ontopic starontopic starontopic starontopic starontopic starontopic starofftopic starofftopic star
Beiträge: 477

Win XP
D3 Prof, D2005 PE
BeitragVerfasst: Fr 30.12.05 18:07 
Welchen Itemindex haben die Radiogroups?
Schließlich machst du den kompletten Ablauf von den einzelnen Indexes abhängig.
Was willst du damit eigentlich bezwecken? Da diese Aktionen nur beim starten durchgeführt werden, hat der User doch gar keine Möglichkeit das zu ändern, oder sehe ich das falsch?
Daher frage ich mich welchen Sinn das macht die If-Abfrage zu machen, da der Itemindex doch Standartmäßig immer "0" ist, es sein denn es wurde von Programmierer anderes definiert.

_________________
I believe that every human has a finite number of heart-beats. I don't intend to waste any of mine running around doing exercises.
- Neil Armstrong
nn1234 Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 41

WIN XP
Delphi 7
BeitragVerfasst: Fr 30.12.05 19:07 
Vom Grundaufbau läuft das Ganze so ab:
Auf Form1 sind Radiogroups mit denen der User jeweils eine Kreatur für sich und eine für den Gegner aussuchen kann. Da ich noch in der Testphase bin, habe ich zunächst eine Kreatur für den Spieler und eine für den Gegner erstellt. Es sollen natürlich weitere folgen, womit die if-Schleife begründet wäre (bis jetzt nur mitt Null, da erst eine Kreatur da ist - Schleife wird noch erweitert). Die ausgewählten Kreaturen sollen dann mit ihrem dazughörigen Level und der Lifeanzeige abgebildet sein, sobald das neue Formular sich öffnet. Das passiert nach klicken eine Buttons.
Soviel zum Aufbau. Da ich FormCreate für mein Problem nicht nutzen kann, wollte ich Timer einbauen, um die Kreaturen abzubilden. Das geht aber nicht. Genauso, wie das verwenden dieser Variablen Erledigt in FormShow.
Was kann ich noch versuchen?
Ich versteh das absolut nicht, da ich vorher eine ähnliche Prozedur in einem anderen Programm geschrieben hatte. Da brauchte ich nach den Methoden den Timer einfach auf Enable := False; stellen und da hat alles ordnungsgemäß funktioniert... :?:
nn1234 Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 41

WIN XP
Delphi 7
BeitragVerfasst: Sa 31.12.05 02:39 
So, hab heute früh viertel vor elf das Problem beschrieben. Nun ist es 13 1/2 Stunden und eine Lösung später... :D
Ich vermute mal, dass der Timer von mir zu schnell auf Enable:=False; gesetzt wurde - das Intervall zu klein war. Hab ich dieses verändert, hat sich aber nichts getan.
Der Fehler lag darin, dass die Eigenschaft Enable direkt nach dem Aufruf der davorigen Methode auf False gesetzt wurde. Somit hat der Timer praktisch keine Zeit, die Methode auszuführen. Methoden, die am Anfang des Timers aufgerufen werden, funktionieren ja (siehe ShowMessage).
Problembehebung:
ausblenden Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
procedure Form2.Timer1Timer(Sender: TObject);

//Springender Punkt!!
procedure Pause(ms: Cardinal); // (c) 2002, Michael Winter
var Stop,Timer: Cardinal;
begin
  Timer := SetTimer(00, ms, nil);
  Stop := GetTickCount + ms;
  repeat
    Application.HandleMessage;
  until Application.Terminated or (Integer(GetTickCount - Stop) >= 0);
  KillTimer(0, Timer);
end;

begin
  {sämtliche Methoden, die der Timer ausführen soll}
  Pause(500);
  Timer1.Enabled := False;
end;

So funktioniert's und ich kann beim Timer bleiben :roll: :lol:
Vielen Dank, für die zahlreichen Anregungen!
nn
Opa
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 22



BeitragVerfasst: Sa 31.12.05 09:07 
Die Lösung mit den 500 mms Pause kann eigentlich nur falsch sein, sie macht nicht wirklich einen Sinn. Wenn dann sollte dort

Application.ProcessMessages oder
Repaint, entweder von der Form bzw. von einem Panel
ggf. auch Panel.DoubleBuffered := true

stehen.

Soll die Procedure Form2.Timer1Timer sofort ausgeführt werden kann man sie u.a. aus Create sofort aufrufen Form2.Timer1Timer(self) oder Form2.Timer1Timer(nil).

Ich denke das der Fehler in Application.HandleMessage steckt ich würde am Ende Application.ProcessMessages wählen.
ausblenden Quelltext
1:
2:
3:
4:
5:
begin  
  {sämtliche Methoden, die der Timer ausführen soll}  
  Application.ProcessMessages 
  Timer1.Enabled := False;  
end;
MSCH
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 1448
Erhaltene Danke: 3

W7 64
XE2, SQL, DevExpress, DevArt, Oracle, SQLServer
BeitragVerfasst: Sa 31.12.05 09:37 
grausam. tse tse

also
versuch's mal Damit

ausblenden Delphi-Quelltext
1:
2:
const
  wm_StartFlag = wm_Application + 1;



in der Klassendeklaration

ausblenden Delphi-Quelltext
1:
procedure WMStartFlag(var Msg:TMessage);Message wm_StartFlag;					


in der OnCreate()-Methode

ausblenden Delphi-Quelltext
1:
postMessage(Self.handle, wm_StartFlag,0,0)					


die Funktion

ausblenden Delphi-Quelltext
1:
2:
3:
4:
[Klasse].WMStartFlag;
begin
  //hier alles ausführen was der Timer machen sollte
end;


Das Vorgehen ist simple, eine Nachricht wird beim Erstellen der form in die
Nachrichtenschleife eingesetzt und erst wenn der Rest abgearbeitet ist, folgt der Aufruf
der Funktion WMStartFlag().

Das funktioniert nur einmal und auch nur via PostMessage().

Vergiss den Kram mit Timer und Variablen.

grez
msch

_________________
ist das politisch, wenn ich linksdrehenden Joghurt haben möchte?