Entwickler-Ecke

Grafische Benutzeroberflächen (VCL & FireMonkey) - Button1.caption --> Button[i].caption ??????


Zippo1000 - Mo 06.01.03 21:45
Titel: Button1.caption --> Button[i].caption ??????
Hallo,
ich habe folgendes Problem:
Ich benutze für die Programmierung eines Brettspiels, 49 (7x7) Buttons. Es sollen auf diesen Buttons Figuren stehen, die bewegt werden können, und dafür ändert sich dann immer die Eigenschaft Caption von den zwei Buttons, die am Zug beteiligt sind. Ich muss aber erst überprüfen, ob der Zug gültig ist, und möchte dann im Nachhinein die Eigenschaft Caption ändern. Dafür müsste ich die Buttons, ähnlich wie ein Array mit Array[i](i ist die Zählervariable) ansprechen können. Also irgendwie sowas wie Button[23].caption:='König'
also irgendwie muss ich da die zahl reinbringen.
Wäre nett, wenn mir jemand weiterhelfen könnte!!!


Raphael O. - Mo 06.01.03 21:57

oben array daklarieren:

Quelltext
1:
var buttons: array[1..10] of Tbutton;                    


dann irgendwo buttons erstellen:

Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
procedure TForm1.Button1Click(Sender: TObject);
begin
buttons[1]:=Tbutton.Create(Form1);
buttons[1].Parent:=form1;
buttons[1].Left:=10;
buttons[1].Top:=10;
buttons[1].Caption:='asd';
end;


Fiji-Fighter


Raphael O. - Mo 06.01.03 22:02

achso: für die onclick-prozedur:

Quelltext
1:
buttons[1].onclick:=meineprozedurfuerbutton1click                    


die prozedur musst du nur irgendwo erstellen...
am besten auch "abhängig" von der Form machen:

Quelltext
1:
2:
3:
4:
procedure Tform1.meineprozedurfuerbutton1click();
begin
...
end;

und im Kopf der unit noch folgendes machen:

Quelltext
1:
2:
3:
type
  TForm1 = class(TForm)
 procedure meineprozedurfuerbutton1click(Sender: Tobject);


Fiji-Fighter


Klabautermann - Mo 06.01.03 22:11

Hallo,

dann würde ich die Buttons Dynamisch erzeugen und in einem 2D Array Halten Also z.B. so:

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:
uses  [...] StdCtrls; // Hier ist der Typ tButton Definiert
type
  TForm1 = class(TForm)
private
    Buttons : ARRAY[1..7,1..7] OF tButton; // Das Button Array
  public
    procedure CreateButtons;
  end;
[...]
procedure TForm1.CreateButtons; // Diese Funtion erstellt die Buttons
  VAR
    i, j : Byte;
begin
  // Zwei verschachtelte Schleifen eine läuft von 1-7 in die Bereite, die andere in die Höhe 
  FOR i := 1 TO 7 DO
    FOR j := 1 TO 7 DO BEGIN
      Buttons[i, j] := tButton.Create(Self); // Den Button i,j erzeugen
      Buttons[i, j].Parent := Self; // Ihn als Kind des Formulars registrieren
      // Den Button Positionieren und auf die richtige größe bringen
      Buttons[i, j].Top := i * 40;
      Buttons[i, j].Left := j * 40;
      Buttons[i, j].Height := 38;
      Buttons[i, j].Width := 38;
      // Und beschriften
      Buttons[i, j].Caption := IntToStr(i) + '\' + IntToStr(j);
    END; // FOR j
end; // Create Buttons
// Nachdem diese Procedre aufgerufen wurde kannst du im ganzenen Formular mit Buttons[X, Y] auf den entsprechenden Knopf zugreifen.


Gruß
Klabautermann


Christian S. - Mo 06.01.03 22:16

Solltest Du Deine Buttons 1-49 allerdings schon erstellt haben, kannst Du auch mit FindComponent arbeiten. Das funktioniert dann so:

Quelltext
1:
TButton(FindComponent('button'+IntToStr(i))).Caption:='irgendwas';                    

Damit weist Du dem Button, der in das Schema Button1, Button2, Button3, ... passt, und der dabei die Nummer i hat, das Caption 'irgendwas' zu.

Es bietet sich hier an, eine Funktion zu bauen, die so aussieht:

Quelltext
1:
2:
3:
4:
function TForm1.mybutton(i : INTEGER) : TButton;
begin
  result:=TButton(FindComponent('button'+IntToStr(i)));
end;

Dann kannst Du mit mybutton(i) sehr viel komfortabler auf Deine Buttons zugreifen.

MfG,
Peter

P.S.: Ich habe in meinen Codes nicht geprüft, ob die gesuchten Komponenten auch wirklich vom Typ TButton sind. Ich bin davon ausgegangen, dass die Namensgebeung so eindeutig ist, dass dies nicht nötig ist.


Zippo1000 - Di 07.01.03 20:46

Hallo,
danke zuerst einmal für die Antworten, die geschrieben wurden. Ich habe mich jetzt dafür entschieden, die Buttons dynamisch als Array zu erstellen, da das dann als zweidimensionales Array echt am schönsten und besten ist. Allerdings hab ich da noch ein Problem. Die Buttons werden doch dann erst zur Laufzeit erstellt, und ich weiß nicht, wie ich dann auf die Prozedur(Methode) zugreifen kann, die einen Mausklick auf den Button behandelt. Diese brauche ich nämlich unbedingt, da ich ja so meine Figuren auf dem Feld ziehen will.

MfG
Philip Weber


Raphael O. - Di 07.01.03 20:55

Hab ich doch eigentlich schon geschrieben... :lol:
na ja

also du musst die prozeduren schon vorher schreiben und kannst dann wenn du die buttons erstellst auf diese prozeduren verweisen...
Ich selber hat folgendes geschrieben:
achso: für die onclick-prozedur:
Code:
buttons[1].onclick:=meineprozedurfuerbutton1click


die prozedur musst du nur irgendwo erstellen...
am besten auch "abhängig" von der Form machen:
Code:

procedure Tform1.meineprozedurfuerbutton1click();
begin
...
end;


und im Kopf der unit noch folgendes machen:
Code:
type
TForm1 = class(TForm)
procedure meineprozedurfuerbutton1click(Sender: Tobject);


Oder hast du das nicht verstanden???
dann frag mal was genauer! :wink:

Fiji-Fighter


Klabautermann - Di 07.01.03 21:48

Hallo,

genau wie Fiji-Fighter sagt. nur das du bei einem Zweidimensionalen Array natürlich für beide Dimensionen ein Array übergeben musst.

Da stellt sich dir wahrscheinlich die Frage, ob du nur eine Funktion machen musst oder für jeden Button eine Eigene. Deshalb quäle ich dich hier mal Profilaktisch mit ein paar Informationen ;).

Die Ereignisbehandlungsroutine ist vom Typ tNotify-Event. Dieser sieht so aus:

Quelltext
1:
type TNotifyEvent = procedure (Sender: TObject) of object;                    


Deine Procedure muss also etwar so aussehen:

Quelltext
1:
2:
3:
4:
procedure TForm1.MyButtonClick(Sender: tObject);
begin
  [...]
end;


Wie bereits gesagt wurde kannst du deinen Buttons dieses Ereignis jetzt zuweisen:

Quelltext
1:
Buttons[1, 1].OnClick := MyButtonClick;                    


Wenn diese Procedure nun aufgerufen wird, dann möchtest du natürlich wissen auf welchen Knopf gedrückt wurde. Auch dadran haben die Delphi entwickler gedacht und dafür den Parameter Sender eingeführt.
Nun ist dieser aber vom Typ tObject und nicht tButton. Dank Polymorphie kann tObjekt als vorfahre aller anderen Objekte jeden anderen Typ enthalten. Du als Programmierer kannst abfragen welcher Typ das ist. Wenn du sichstellen willst eröffnest du deine Behandlungsrutine am besten mit der IF-Abfrage:

Quelltext
1:
IF (Sender IS tButton) THEN                    

Wenn du nun weißt, das du einen TButton hast kannst du per Type-Cast auch an alle Methoden und Eigenschaften des Buttons ran:

Quelltext
1:
  tButton(Sender).Caption := 'Der war''s';                    

Oder du verwendest eine Hilfsvariable, damit du nicht ständig Casten musst. Das nun folgende Beispiel geht davon aus, das du den Button an seiner Caption erkennst:

Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
procedure TForm1.MyButtonClick(Sender: tObject);
  VAR
    ActButton : tButton;
begin
  IF (Sender IS tButton) THEN BEGIN
    ActButton := tButton(Sender);
    IF (ActButton.Caption = 'X') THEN
      ShowMessage('Den solltest du doch nicht drücken.');
  END;
end;


Natürlich kannst du auch jede andere Identifizierungsmöglichkeit nutzen (inklusive des Vergleichs mir den Elementen deines Arrays).

Gruß
Klabautermann


Wolff68 - Mi 08.01.03 20:21

Klabautermann hat folgendes geschrieben:
Natürlich kannst du auch jede andere Identifizierungsmöglichkeit nutzen (inklusive des Vergleichs mir den Elementen deines Arrays).
Ich verwende für sowas auch mal ganz gerne die Eigenschaft Tag. Als Integer zB recht gut für eine Nummerierung geeignet, und hat ansonsten ja keine Funktion.

(Wobei Du mit DIV und MOD auch schnell bei Zeile und Spalte bist)


Zippo1000 - Fr 10.01.03 19:19

Hallo,

vielen Dank für die zahlreichen Antworten. Ich glaube, dass ich jetzt alles weiß, was ich brauche.
Ich finde es echt super, dass sich Leute, die einiges in Delphi drauf haben, doch die Mühe machen, Leuten wir mir, die irgendwie feststecken, zwar eine Idee haben, aber nicht wissen, wie die umzusetzen ist, weiterhelfen. Danke!!!
Anscheinend machen sich einige Leute auch wirklich gedanken, denn ich wollte eigentlich noch fragen, wie ich denn jetzt weiß, welcher Button gedrückt worden ist, aber die Antwort auf meine Frage, wurde schon gegeben, noch bevor ich sie aufschreiben konnte. Vielen Dank an Klabautermann für seine kompetenten Antworten und seine hellseherischen Fähigkeiten, oder zumindest seine Mühe, sich in mein Problem hineinzudenken.
Also ich werde dieses Forum auf jeden Fall weiterempfehlen, und versuche, auch selbst ein paar Antworten zu geben.
Nochmal Danke
Gruß
Zippo1000


Klabautermann - Fr 10.01.03 22:20

Wolff68 hat folgendes geschrieben:
Ich verwende für sowas auch mal ganz gerne die Eigenschaft Tag. Als Integer zB recht gut für eine Nummerierung geeignet, und hat ansonsten ja keine Funktion.
(Wobei Du mit DIV und MOD auch schnell bei Zeile und Spalte bist)

Stimmt. Für solche Zwecke ist er ja auch da ;). Habe ich in dem Moment gar nicht dran gedacht.

Zippo1000 hat folgendes geschrieben:
Ich finde es echt super, dass sich Leute, die einiges in Delphi drauf haben, doch die Mühe machen, Leuten wir mir, die irgendwie feststecken, zwar eine Idee haben, aber nicht wissen, wie die umzusetzen ist, weiterhelfen.

Wer sagt denn, dass wir nicht auch hin und wieder mal feststecken und dann gerne auch mal die Hilfe anderer in anspruch nehmen.

Zippo1000 hat folgendes geschrieben:
Danke!!!

Gern geschehen.

Gruß
Klabautermann