Entwickler-Ecke

Delphi Language (Object-Pascal) / CLX - Klassen, Arrays.... simple Frage


Sylvus - So 30.08.09 14:12
Titel: Klassen, Arrays.... simple Frage
hay Leute, also ich will folgendes:
Ein Object das 8 Bilder beinhaltet. Jedes dieser Bilder will ich verändern, so das ein gesammtes Bild entsteht.
Diese Objekte, bestehend aus 8 Bildern will ich mehrmals in verschiedenen Variationen anzeigen lassen.
Jetzt hatte ich als erstes folgendes Code geschrieben:


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:
type
  TEAnzeige = class(TObject)
    EGrafic: TImage;
  public
    procedure erzeuge(pos: TPoint; img_name: string);
  end;

  TAnzeige = array[1..8of TEAnzeige;

  var
  Anzeigen:array[0..3of TAnzeige;

implementation
uses Unit1;



procedure TEAnzeige.erzeuge(pos: TPoint; img_name: string);
begin
  EGrafic := TImage.Create(Form1);
  EGrafic.Left := pos.X;
  EGrafic.Top := pos.Y;
  EGrafic.Name := img_name;
  EGrafic.Width := 50;
  EGrafic.Height := 400;
  EGrafic.Canvas.Brush.Color := clblack;
  EGrafic.Canvas.Rectangle(00, EGrafic.Width, EGrafic.Height);
end;


Und wollte das ganze Bild jetzt mit folgender Anweisung erzeugen:


Delphi-Quelltext
1:
Anzeigen[1].TAnzeige[1].TEAnzeige.erzeuge(temp_pos,'Bla');                    



aber das klappt nicht :P Jetzt wollte ich euch fragen, wie man soetwas grundsätzlich macht^^ Also ich wills ja auch etwas elegant lösen :) Viele Grüße Sylvus


BenBE - So 30.08.09 15:53

Eine TEAnzeige solltte alle 8 Teilbilder beinhalten. Hierbei bietet es sich an, nur das Gesamtbild zu speichern und für die Reproduktion ggf. nur die Ausschnittsnummer und die zu verwendende Zielposition zu übergeben.

So wie deine Struktur jetzt ist, erzeugst Du durch die zahlreichen Objekte unnötig Overhead. Zudem gehört das Ausgeben der Teilbilder zu den Aufgaben der EAnzeige, nicht zu denen der einzelnen Teilbilder.

Und auch sonst solltest Du eher TPicture statt TImage verwenden.


Sylvus - So 30.08.09 16:07

Hab das jetzt mal geändert. TImage hab ich aber immer noch drin, weil ich ja mit Canvas gerne was zeichnen möchte.
Leider startet das Programm immer noch nicht.
Folgender Code:


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:
type
  TAnzeige = class(TObject)
    Grafic:array[1..8of TImage;
  public
    procedure erzeuge(pos: TPoint; img_name: string; img:integer);
  end;



var
  Anzeigen: array[0..3of TAnzeige;

implementation
uses Unit1;



procedure TAnzeige.erzeuge(pos: TPoint; img_name: string; img:integer);
begin
  Grafic[img] := TImage.Create(Form1);
  Grafic[img].Parent:=Form1;
  Grafic[img].Left := pos.X;
  Grafic[img].Top := pos.Y;
  Grafic[img].Name := img_name;
  Grafic[img].Width := 50;
  Grafic[img].Height := 400;
  Grafic[img].Canvas.Brush.Color := clblack;
  Grafic[img].Canvas.Rectangle(00, Grafic[img].Width, Grafic[img].Height);
end;

und

Delphi-Quelltext
1:
Anzeigen[0].erzeuge(temp_pos,'Bla',1);                    


Es hängt jetzt an: Grafic[img] := TImage.Create(Form1);
hab auch schon self oder TAnzeige versucht, aber da bekomm ich auch verschiedene Fehlermeldungen.
Vielleicht dazu noch ein Tip? Danke!
Grüße Sylvus


platzwart - So 30.08.09 16:10

Verrätst du uns nun auch noch die Fehlermeldung?!?


Sylvus - So 30.08.09 16:18

naja bei
Grafic[img] := TImage.Create(Form1);
kommt
Exception-Klasse EAccessViolation mit Meldung 'Zugriffsverletzung bei Adresse 0046490A in Modul 'Project1.exe'. Schreiben von Adresse 00000004'. Prozess Project1.exe (2396)

bei
Grafic[img] := TImage.Create(self);
kommt
[DCC Fehler] Unit2.pas(44): E2010 Inkompatible Typen: 'TComponent' und 'TAnzeige'

und bei
Grafic[img] := TImage.Create(TAnzeige);
kommt
[DCC Fehler] Unit2.pas(44): E2010 Inkompatible Typen: 'TComponent' und 'Class reference'

:) Weiß aber nichts damit anzufangen, ja bin etwas dumm^^

//edit
so ist das kein problem:

Quelltext
1:
2:
3:
4:
var
Ima:Timage;
begin
  Ima:= TImage.Create(Form1);


warum geht das andere nicht? Bzw. ist der Funktionsaufruf korrekt?
Grüße Sylvus


platzwart - So 30.08.09 16:57

Naja, mit Dummheit hat das nix zu tun, ein wenig mehr Selbstbewusstsein bitte ;)

Also, eine "EAccessViolation" deutet fast immer darauf hin, dass du auf ein Objekt zugreifst, das garnicht existiert. Das mit dem "Form1" in TImage.Create(Form1); sollte schon passen. Muss mir das nochmal genauer anschaun ;)


Sylvus - So 30.08.09 17:00

hmmmm liegts hierdran:


Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
procedure TForm1.Button1Click(Sender: TObject);
var
temp_pos:TPoint;
begin
temp_pos.X:=0;
temp_pos.Y:=0;
Anzeigen[1].erzeuge(temp_pos,'Bla',1);
end;


aber sollte eiegntlich gehen oder?
Grüße Sylvus


platzwart - So 30.08.09 17:14

Aaaaah, ok, ich denke, ich habe da was gefunden ;)

TEAnzeige ist eine Klasse. Wenn du nun folgendes schreibst...


Delphi-Quelltext
1:
TAnzeige = array[1..8of TEAnzeige;                    


... so bedeutet das lediglich, dass das Array 8 Objekte der Klasse TEAnzeige aufnimmt, nicht aber, dass diese Objekte auch existieren! Dass heißt, du musst für jedes Element dieses Arrays ein Objekt der Klasse TEAnzeige erzeugen, bevor du darauf zugreifst ;)


Sylvus - So 30.08.09 17:18

ah also muss ich die Objekte bzw. das Array erst erstellen...
ich kann jetzt aber nicht:

Anzeigen[0] := TAnzeige.Create;

schreiben oder? Also wie mach ich das ganze jetzt? Sonst vielleicht Link zu nem Tutorial?
Danke für die Mühe!
Grüße Sylvus


platzwart - So 30.08.09 17:19

EDIT:

Du hast den Code ja geändert gehabt, für den letzten Stand gilt folgendes:

"TAnzeige" ist nur eine Klasse, aber kein reales Objekt.


Delphi-Quelltext
1:
Anzeigen: array[0..3of TAnzeige;                    


Hier musst du also die Objekt des Arrays "Anzeigen" erst erzeugen. Deine Prozedur "erzeuge" wäre als Konstruktur wahrscheinlich besser geeignet...


Sylvus - So 30.08.09 17:29

ja aber das könnte ich ja für beides benutzten. Ich will ja da auch die Bilder erzeugen.
Weiß aber grad immer noch nicht wie es geht, hab jetzt vor den Funktionsaufruf folgendes geschrieben:

Anzeigen[1]:= TAnzeige.Create;
Anzeigen[1].erzeuge(temp_pos,'Bla',1);

Es funktioniert jetzt auch endlich, weiß aber nicht ob das jetzt auch sauber programmiert ist :)
Sollte ich das leiber anders machen? Aber ich kann auf jeden Fall schonmal weiter arbeiten!
Danke euch!


Grüße Sylvus


platzwart - So 30.08.09 17:46


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:
52:
type
 TAnzeige = class
  private
   FGrafic:array[1..8of TImage;
  public
   constructor Create();
   destructor Destruct();
   procedure SichtbarMachen(pos: TPoint; img_name: string; img:integer);
   property Grafic[Index: Integer]: TImage read rd_Grafic; default;
 end;

constructor TAnzeige.Create;
var
 i: Integer
begin
 inherited Create;
 For i:=1 to 8 do
  begin
   self.FGrafic[i]:= TImage.Create;
   self.FGrafic[i]:= TImage.Create(Form1);
   //self.FGrafic[i].Parent:= Form1; brauchst du nicht, erledigt die Zeile obendrüber ;)
   self.FGrafic[i].Visible:= False; // erzeugen, aber erstmal verstecken...
  end;
end;

destructor TAnzeige.Destruct;
var
 i: Integer;
begin
 For i:=1 to 8 do
  begin
   self.FGrafic[i].Free;
  end;
 inherited;
end;

function TAnzeige.rd_Grafic(Index: Integer): TImage;
begin
 Result:= self.FGrafic[Index];
end;

procedure TAnzeige.SichtbarMachen(pos: TPoint; img_name: string; img:integer);
begin
 self.FGrafic[img].Left := pos.X;
 self.FGrafic[img].Top := pos.Y;
 self.FGrafic[img].Name := img_name;
 self.FGrafic[img].Width := 50;
 self.FGrafic[img].Height := 400;
 self.FGrafic[img].Canvas.Brush.Color := clblack;
 self.FGrafic[img].Canvas.Rectangle(00, Grafic[img].Width, Grafic[img].Height);
 self.FGrafic[img].Visible:= True; // ab hier ist es sichtbar...
end;


Hab ich jetzt mal so runtergetippt ohne zu Testen, also mit Vorsicht zu genießen ;)

Verwenden kannst du das dann wie folgt:

Deklarieren:

Delphi-Quelltext
1:
2:
var
  Anzeigen: array[0..3of TAnzeige;


Initialisieren:

Delphi-Quelltext
1:
2:
 For i:=0 to 3 do
  Anzeigen:= TAnzeige.Create;


Verwenden:

Delphi-Quelltext
1:
  Anzeigen[2][3].SichbarMachen(TPoint(100,150), 'Blubb'4)