Entwickler-Ecke

Grafische Benutzeroberflächen (VCL & FireMonkey) - Variablen werden zu 0?!


mosa - Di 30.12.08 13:52
Titel: Variablen werden zu 0?!
Hallo,
Ich bin noch ein Anfänger und habe ein komisches Problem:
Wenn ich zwei Formulare habe und in Form1 habe ich eine Trackbar, von der ich den Wert (also tb1.position) an Form2 übergeben will. Geht aber nicht... Ich habe dann mal zum Testen auf dem zweiten Formular ein Label platziert, dass mit form1.tb1.position ausgibt, und da steht immer 0 drauf. Wie kommt das? was mache ich falsch?

Auch wenn ich vor dem öffnen von form2 tbposition:=tb1.position in form1 mache und tbposition in dem Label anzeigen lasse, steht da 0...

Ich benutze Delphi 2007 auf Vista HP

Viele Grüße

MoSa


Gausi - Di 30.12.08 14:15

Hallo und :welcome: in der Entwickler-Ecke!

Hast du evtl. die Variable tbposition doppelt deklariert? Einmal in Form1 und dann nochmal in Form2?

Wenn man z.B. im OnChange-Event der Trackbar sowas macht:

Delphi-Quelltext
1:
2:
3:
4:
procedure TForm1.TrackBar1Change(Sender: TObject);
begin
    Form2.Caption := Inttostr(Trackbar1.Position);
end;
, dann funktioniert das einwandfrei. :D


baka0815 - Di 30.12.08 14:23

Ich vermute, dass es sich hier um den Unterschied in der Übergabe per Wert (by value) oder per Referenz (by reference) handelt.

Wenn du TbPosition als Integer definiert hast, dann wird dies immer by value verwendet. Wenn du also folgendes hast:


Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
var
  TbPosition: Integer;

[...]

begin
  TbPosition := Tb1.Position; // es wird der Wert zu diesem Zeitpunkt übergeben
end;


dann steht in TbPosition immer der Wert, den die Trackbar zu dem Zeitpunkt der Zuweisung hatte. Weitere Änderungen werden dann nicht automatisch übernommen.
Dazu kannst du, wie Gausi schrieb, das Change-Ereignis der Trackbar verwenden.
Wenn du dort jedoch nur die Zuweisung auf TbPosition := Tb1.Position vornimmst, dann wird dein Label auf dem zweiten Formular noch nicht aktualisiert. Das musst du dann separat (auch im Change-Ereignis) machen.


jaenicke - Di 30.12.08 14:23

Hier im Anhang habe ich ein kleines Projekt angehängt, zwei Formulare, im zweiten wird der Wert angezeigt. Das habe ich grad schnell mit Delphi 2007 gemacht.

Du könntest auch konkret deinen Code bzw. die entsprechenden Teile davon posten. Wann du zum Beispiel den Wert ausliest. Denn anfangs ist der Wert ja 0. Auf eine Änderung des Wertes kannst du mit OnChange bei der TrackBar reagieren wie du es hier im Anhang auch siehst und auch schon gesagt wurde.


mosa - Di 30.12.08 14:25

Nein, ich habe nichts doppelt deklariert... Und bei der trackbar im onchange event hatte ich auch schon stehen

tbposition:=tb1.position;

oder ich die position testweise auch in einem label in form1 gespeichert, also:

LTBPosition.caption:=IntToStr(tb1.position);


Doch wenn ich diese Werte in form2 aufrufe steht immer 0 da.
Außerdem habe ich auch schon die Variablen umbrnannt und ganz ohne var's gearbeitet (Also Label12.caption:=IntToStr(Form1.TB1.Position);) aber auch das klappt nicht. Ich habe die TB in einer Groupbox liegen, kann man da irgendwelche Fehler machen? oder muss ich noch irgendwo deklarieren, dass die Vars von Form2 aufgerufen werden dürfen (Außer in der Uses liste)?
Vielen Dank trotzdem
MoSa


jaenicke - Di 30.12.08 14:29

Du könntest dein Projekt einfach anhängen (.pas, .dfm, .dpr als Zip) wenn du möchtest, dann sehen wir sicher woran es liegt. ;-)
Und in meinem Beispiel siehst du ja, dass es eigentlich so funktioniert, ich habe ja in dem Button den Wert auch direkt abgerufen.

// EDIT:
Ob die Trackbar in einer GroupBox liegt oder wo anders macht keinen Unterschied. Ich vermute eher, dass es mehrere Instanzen des Formulars gibt, z.B. weil du das Formular manuell nochmal erzeugst oder sowas. Und dann sprichst du vielleicht die falsche an.


mosa - Di 30.12.08 16:29
Titel: Übergabe funktioniert!
So, Die Übergabe funktioniert jetzt, aber nun kommt gleich das nächste Problem: Ich gebe einige Werte in Label aus, die von der TB-Position abhängen, also z.B. wert:=TB.Position*24. Doch bei der Ausgabe stehen jetzt immer die gleichen Werte...


Ich hänge den Quelltext gleich an...
Mfg
MoSa

//Edit: Hier ist er


jaenicke - Di 30.12.08 16:45

Jetzt verstehe ich glaube ich wo das Problem ist. ;-)
Du benutzt OnCreate des zweiten Formulars. Du erzeugst es aber nicht jedesmal neu sondern zeigst es nur an!

Delphi-Quelltext
1:
  Form2.Show;                    
Wenn du Show aufrufst, wird nicht OnCreate aufgerufen sondern OnShow, deshalb musst du deinen Quelltext dort hineinschreiben.

// EDIT:
Ach ja: statt

Delphi-Quelltext
1:
2:
  Form1.Enabled:=False;
  Form2.Show;
kannst du auch schreiben

Delphi-Quelltext
1:
  Form2.ShowModal;                    
;-)
Ein Unterschied ist, dass Code nach ShowModal in der Prozedur erst nach dem Schließen des zweiten Formulars ausgeführt wird. Du willst aber auf Form1 ja ohnehin nichts machen.


baka0815 - Di 30.12.08 16:48

Das Problem liegt hier:

Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
procedure TForm2.FormCreate(Sender: TObject);
Var Ressourcen2, Schwer, Ressourcen3:Integer;
begin
  Ressourcen2:=(StrToInt(Label11.Caption)+1)*100;
  //TBs Auslesen:
  Schwer:=Form1.TBStaerke.Position;
  //Startressourcen zuweisen
  Steine.anzahl:=Ressourcen2*12;
  Holz.anzahl:=Ressourcen2*15;
  Gold.anzahl:=Ressourcen2*04;
  Metall.anzahl:=Ressourcen2*09;
  Arbeiter:=round(Ressourcen2/10);
  Nahrung.anzahl:=Ressourcen2*12;
  Bevoelkerungsmax:=Arbeiter*2;
  Platz:=Ressourcen2;
  PlatzMax:=round(Platz*1.5);
  Haeuser:=2;
  Felder:=5;

  werteausgabe;
end;


Das OnCreate-Ereignis wird direkt beim Programmstart aufgerufen (das Formular steht im Projekt unter den automatisch zu erzeugenden). Dann steht in Label11.Caption natürlich '0' drin und somit wählt er immer 1 für Ressourcen2.

Diese Berechnung solltest du dahin verschieben, wo du auch Label11.Caption zuweist oder in das OnShow-Ereignis des Formulars.

Du solltest dir außerdem überlegen ob du die Typen für Ressourcen, etc. nicht in eine separate Datei UTypes.pas oder so packen solltest, damit du auch in weiteren Units darauf zugreifen kannst und nicht immer das Formular mit einbinden musst.
In einer Datei mit einem Formular sollten grundsätzlich nur Dinge stehen, die genau mit dem Formular zu tun haben - am Besten nur mit dem Aussehen. Berechnungen, etc. sollten davon getrennt in separaten Units sein.