Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   GUI-Design mit VCL / FireMonkey / Common Controls (https://www.delphipraxis.net/18-gui-design-mit-vcl-firemonkey-common-controls/)
-   -   Delphi TList generische Liste Fehler beim deklarieren RTTI (https://www.delphipraxis.net/162188-tlist-generische-liste-fehler-beim-deklarieren-rtti.html)

H3llsing 11. Aug 2011 12:46


TList generische Liste Fehler beim deklarieren RTTI
 
Moin zusammen,

ich komm einfach nich drauf was ich falsch mache.

Hintergrund: ich habe ein Array of Record, dieses möchte ich gern in einer procedure durchlaufen also

myRec[0].eigenschaft1
myRec[0].eigenschaft2
...

Nun bin ich durch längere Suche auf die generischen Tlist gestoßen.

Allerdings bekomm ich einen Compilerfehler :/

Delphi-Quellcode:
uses Classes;
...
type
  TZuordnung = record
  Zuorndungsname     :string;
  trennzeichen       :string;
  Zuordnungsdatei    :string;
  distributor        :string;
  ...
end;
type Tar_Zuordnung = array of Tzuordnung;
type TlstZuordnung = Tlist<TZuordnung>; //compiler wirft Fehler raus: "undeklarierter Bezeichner 'Tlist' '1' in Zeile..."

end;
Was mach ich also falsch ?!

verwende Delphi2010

VIELEN dank ;) hab ich bei der suche nirgens gefunden =)

Ralf Kaiser 11. Aug 2011 12:49

AW: TList generische Liste Fehler beim deklarieren
 
Zitat:

Zitat von H3llsing (Beitrag 1116216)
Delphi-Quellcode:
uses Classes;
...
Was mach ich also falsch ?!

verwende Delphi2010

Das hier:

Delphi-Quellcode:
uses
Generics.Collections, Generics.Defaults;

Stevie 11. Aug 2011 13:12

AW: TList generische Liste Fehler beim deklarieren
 
Wenn du eh schon ein array hast, warum das nicht an die Prozedur übergeben?

H3llsing 11. Aug 2011 13:45

AW: TList generische Liste Fehler beim deklarieren
 
ich frage mich grade ob das überhaupt möglich ist mit der Tlist was ich vorhabe.

Zitat:

Hintergrund: ich habe ein Array of Record, dieses möchte ich gern in einer procedure durchlaufen also

myRec[0].eigenschaft1
myRec[0].eigenschaft2
kann ich mir alle eigenschaften von myRec[0] anzeigen lassen ?

sowas in der art:
Delphi-Quellcode:
//PSEUDO-Code
for i:=0 to myRec[0].countPropertys -1 do
property := Myrec[0][i]; // gibt eigenschaft 1 dann 2 dann 3 etc aus
ist das mit dem Array oder mit der Tlist erreichbar ?

Stevie 11. Aug 2011 14:56

AW: TList generische Liste Fehler beim deklarieren
 
Ja, mit RTTI:
Delphi-Quellcode:
uses
  Rtti, TypInfo;

procedure PrintStuff(const Item: TMyRecord);
var
  ctx: TRttiContext;
  t: TRttiType;
  f: TRttiField;
  p: TRttiProperty;
begin
  t := ctx.GetType(TypeInfo(TMyRecord));
  if Assigned(t) then
  begin
    for f in t.GetFields do
    begin
      if f.Visibility in [mvPublic..mvPublished] then
        Writeln(f.Name + ' = ' + f.GetValue(@Item).ToString);
    end;

    for p in t.GetProperties do
    begin
      if p.Visibility in [mvPublic..mvPublished] then
        Writeln(p.Name + ' = ' + p.GetValue(@Item).ToString);
    end;
  end;
end;

H3llsing 11. Aug 2011 15:18

AW: TList generische Liste Fehler beim deklarieren
 
Vielen Dank @Stevie

Genau sowas habe ich Gesucht!
Funktioniert einwandfrei =)

shmia 11. Aug 2011 16:44

AW: TList generische Liste Fehler beim deklarieren RTTI
 
Wieso macht du eigentlich aus TZuordnung keine Klasse?
Du hast ja wahrscheinlich Prozeduren/Funktionen, die mit den Inhalten von TZuordnung arbeiten.
Grundlage von OOP ist ja, dass Daten und Programmcode der mit diesen Daten arbeitet zu einem "Paket" zusammengeschnürt werden und das ist eben eine Klasse.

Uwe Raabe 12. Aug 2011 00:17

AW: TList generische Liste Fehler beim deklarieren RTTI
 
Zitat:

Zitat von shmia (Beitrag 1116286)
Wieso macht du eigentlich aus TZuordnung keine Klasse?
Du hast ja wahrscheinlich Prozeduren/Funktionen, die mit den Inhalten von TZuordnung arbeiten.
Grundlage von OOP ist ja, dass Daten und Programmcode der mit diesen Daten arbeitet zu einem "Paket" zusammengeschnürt werden und das ist eben eine Klasse.

Das geht in vielen Fällen genausogut mit Records und man spart sich das Erzeugen und Freigeben. Ich glaube allerdings noch nicht mit Delphi 5...

H3llsing 12. Aug 2011 09:19

AW: TList generische Liste Fehler beim deklarieren RTTI
 
OOP ist mir schon geläufig aber genau wie Uwe es schon gesagt hat, geht es in meinem Fall nur mit dem Record besser =)

shmia 12. Aug 2011 10:33

AW: TList generische Liste Fehler beim deklarieren RTTI
 
Zitat:

Zitat von H3llsing (Beitrag 1116363)
...geht es in meinem Fall nur mit dem Record besser =)

Bist du sicher?
Die drei Punkte in deinem Record deuten ja an, dass es dort noch mehr Daten gibt.
Bei sehr kleinen Records, z.B. nur x,y,z-Koordinaten, hat ein Record absolut seine Berechtigung.
Wenn es aber mehr Daten werden, dann muss es zwangläufig auch mehr Code geben, der mit den Daten arbeitet.
Das verlangt dann nach einer Klasse.
Ich muss nur immer wieder feststellen dass selbst altgediente Hasen manchmal nicht beweglich genug sind vom Record auf eine Klasse zu wechseln.
Sehr häufig wird auch der Fehler begangen, dass der Record quasi identisch ist mit der Struktur, mit der Daten geladen & gespeichert werden.
Damit wird aber die Veränderung der Software stark behindert.
Bei einer Klasse gäbe es dagegen die Methoden LoadFromStream() und SaveToStream().
So kann die interne Repräsentation der Daten effektiv von der externen Repräsentaion auf einem Speichermedium entkoppelt werden.

jaenicke 12. Aug 2011 11:08

AW: TList generische Liste Fehler beim deklarieren RTTI
 
Zitat:

Zitat von shmia (Beitrag 1116374)
Bei einer Klasse gäbe es dagegen die Methoden LoadFromStream() und SaveToStream().

Bei einem Record genauso, wenn man das möchte.

Uwe Raabe 12. Aug 2011 12:11

AW: TList generische Liste Fehler beim deklarieren RTTI
 
Zitat:

Zitat von shmia (Beitrag 1116374)
Ich muss nur immer wieder feststellen dass selbst altgediente Hasen manchmal nicht beweglich genug sind vom Record auf eine Klasse zu wechseln.

Und ich muss immer wieder feststellen, daß manche Hasen nicht beweglich genug sind, die Techniken neuerer Delphi-Versionen einzusetzen. Dazu gehören, neben einer Fülle anderer Dinge, auch Methoden in Records.

H3llsing 12. Aug 2011 14:45

AW: TList generische Liste Fehler beim deklarieren RTTI
 
Zitat:

Zitat von H3llsing (Beitrag 1116363)
OOP ist mir schon geläufig aber genau wie Uwe es schon gesagt hat, geht es in meinem Fall nur mit dem Record besser =)

Ich glaub das ist jetzt nicht mehr so ganz zutreffend!

Mitlerweile sind etliche Funktionen und Proceduren hinzugekommen und ich denke die Verwaltung durch eine Klasse wäre mitlerweile der bessere weg.

Da ich in Delphi bisher nur wenig mit Klassen gearbeitet habe würde ich gerne wissen
wie man das ganze mit soeinem Array Record realisiert.

Delphi-Quellcode:
//Methoden
function getZuordnungen():Tar_zuordnung; //holt alle Zuordnungen aus DB und liefert Array of TZuordnung zurück
procedure fillCombobox(ar_zuordnung:Tar_zuordnung); //füllt die ComboBox mit den Zuordnungsnamen

procedure verbindeFeld(); //verbindet die beiden Treeview Datenfelder miteinander und Speichert Zuordnungswerte in DB
procedure entferneFeld(TV:ttreeview); //entfernt die Verbindungen
procedure ladeVerbindungen(ar_zuordnung :Tar_Zuordnung;id:integer);//fügt Unterknoten mit den vorhanden Zuordnungswerten in die Treeviews ein

Wie realisiert man das ?

Mein Ansatz:
Delphi-Quellcode:
unit uZuordnungsklasse;

interface

uses Classes;
type
  TZuordnungRec = record
    zuorndungsname     :string;
    trennzeichen       :string;
    zuordnungsdatei    :string;
    distributor        :string;
    ...
  end;

type Tar_ZuordnungRec = array of TZuordnungRec;
type
  TZuordnung = class
    Constructor create;
    Destructor destroy;
    private
      ZO = TzuordnungRec;
    public
     //zugriffsmethoden
end;



implementation

end.

DeddyH 12. Aug 2011 14:48

AW: TList generische Liste Fehler beim deklarieren RTTI
 
Lass den Record weg und mache aus seinen Feldern Properties Deiner Klasse. Verwalten kannst Du sie dann über eine TObjectList. Wenn diese die Objekte beim Entfernen automatisch freigeben soll, lässt Du deren OwnsObjects-Eigenschaft auf true, ansonsten eben umstellen.

H3llsing 12. Aug 2011 15:26

AW: TList generische Liste Fehler beim deklarieren RTTI
 
okay ich versuch mich mal dran =)
hab bisher noch nicht mit Tobjektlist gearbeitet aber DelphiTreff hat ja immer n Tutorial parat.

also müsst ich so mein Gerüst umbaun ?
Delphi-Quellcode:
type
  TZuordnung = class
    Constructor create; override;
    Destructor destroy; override;
    private
      Fzuorndungsname     :string;
      Ftrennzeichen       :string;
      Fzuordnungsdatei    :string;
      Fdistributor        :string;
      ...
    public
     
     // methoden

     //propertys
      property zuorndungsname     :string read Fzuorndungsname write Fzuorndungsname;
      property trennzeichen       :string read Ftrennzeichen write Ftrennzeichen;
      property zuordnungsdatei    :string read Fzuordnungsdatei write Fzuordnungsdatei;
      property distributor        :string read Fdistributor write Fdistributor;
      ...

end;
und wo werden dann meine instancen der Objektlist hinzugefügt?
Muss die Objektlist Global defininiert werden, damit ich von mehreren Buttons drauf zugreifen kann ? ?

oder wird einfach eine Methode GetZuordnungen :Tobjektlist, die mir alle Zuordnungen in klassen in die Objektlist packen und zurückgibt ausreichen ?!

DeddyH 12. Aug 2011 15:34

AW: TList generische Liste Fehler beim deklarieren RTTI
 
Schon ganz gut. Wenn die Buttons alle auf demselben Formular liegen, würde ich die Liste als privates Feld des Formulars deklarieren.
Delphi-Quellcode:
uses Contnrs; //oder Generics.Collections für eine generische TObjectList

type
  TZuordnung = class  
  private
    FZuordnungsname: string;
    //usw.
  public
    constructor Create;
    destructor Destroy; override;
    property Zuordnungsname: string read FZuordnungsname write FZuordnungsname;
  end;

  TDeinForm = class(TForm)
  private
    FListe: TObjectList;
...

procedure TDeinForm.btnNeueZuordnungClick(Sender: TObject);
var
  Zuordnung: TZuordnung;
begin
  Zuordnung := TZuordnung.Create;
  Zuordnung.Zuordnungsname := 'Ding Dong, die Hex ist tot';
  FListe.Add(Zuordnung);
end;
So geht das prinzipiell. FListe muss natürlich noch erzeugt und später freigegeben werden (z.B. im OnCreate/OnDestroy).

Stevie 12. Aug 2011 15:44

AW: TList generische Liste Fehler beim deklarieren RTTI
 
Zitat:

Zitat von H3llsing (Beitrag 1116452)
hab bisher noch nicht mit Tobjektlist gearbeitet aber DelphiTreff hat ja immer n Tutorial parat.

Oh, bitte nicht! Da du Delphi 2010 hast, benutz die TObjectList<T> aus der Generics.Collections.pas

H3llsing 12. Aug 2011 16:20

AW: TList generische Liste Fehler beim deklarieren RTTI
 
Wieso kracht es hier ?

Delphi-Quellcode:
uses Generics.Collections,uZuordnungsklassen ...;

type
  TfrmZuordnung = class(TForm)
  ...
  private
    FListe: TObjectList<Tzuordnung>;
     ...
  end;


procedure TfrmZuordnung.FormCreate(Sender: TObject);
begin
  Fliste.create(); //hier kommt AV ?!
end;

DeddyH 12. Aug 2011 16:23

AW: TList generische Liste Fehler beim deklarieren RTTI
 
Dass Dir das noch passiert.
Delphi-Quellcode:
var Dings: TDings;
Dings := TDings.Create;

H3llsing 12. Aug 2011 16:27

AW: TList generische Liste Fehler beim deklarieren RTTI
 
*HUST* ja wollts grad wieder wegmachen :D
Der tag ist schonwieder viel zu lang ;)

wird mal Zeit für 5 minuten pause!

H3llsing 12. Aug 2011 16:43

AW: TList generische Liste Fehler beim deklarieren RTTI
 
hmm warum meckert eigentlich die Umgebung bei

Delphi-Quellcode:
var
  Zuordnung: TZuordnung;
begin
  Zuordnung := TZuordnung.Create('ALSO');
  FListe.Add(Zuordnung);

  JvComboBox_zuordnung.Clear;
  JvComboBox_zuordnung.Items.Add(Fliste.Items[0].zuordnungsname); // zuordnungsname ist nicht deklarierter bezeichner
end;
Aber funktionieren tuts trotzdem!

DeddyH 12. Aug 2011 16:48

AW: TList generische Liste Fehler beim deklarieren RTTI
 
Und wenn Du das Items weglässt?
Delphi-Quellcode:
FListe[0].Zuordnungsname
Ansonsten einfach ignorieren, das wird wohl mal wieder Error Insight sein. Evtl. ist der Effekt weg, wenn Du das Projekt anschließend schließt und neu öffnest.

Stevie 12. Aug 2011 16:56

AW: TList generische Liste Fehler beim deklarieren RTTI
 
Zitat:

Zitat von H3llsing (Beitrag 1116481)
hmm warum meckert eigentlich die Umgebung bei

Delphi-Quellcode:
var
  Zuordnung: TZuordnung;
begin
  Zuordnung := TZuordnung.Create('ALSO');
  FListe.Add(Zuordnung);

  JvComboBox_zuordnung.Clear;
  JvComboBox_zuordnung.Items.Add(Fliste.Items[0].zuordnungsname); // zuordnungsname ist nicht deklarierter bezeichner
end;
Aber funktionieren tuts trotzdem!

Error Insight hat arge Probleme, was Generics angeht und unterkringelt da allerhand Blödsinn. Einfach ignorieren (oder wie ich ausschalten).

H3llsing 15. Aug 2011 10:03

AW: TList generische Liste Fehler beim deklarieren
 
Ein Problem hab ich nun noch mit der klasse.
Wie bekomme ich denn so wie beim Array mit RTTI alle Feldnamen?
Also bei meiner Klasse die ganzen Properties?

Zitat:

Zitat von Stevie (Beitrag 1116258)
Ja, mit RTTI:
Delphi-Quellcode:
uses
  Rtti, TypInfo;

procedure PrintStuff(const Item: TMyRecord);
var
  ctx: TRttiContext;
  t: TRttiType;
  f: TRttiField;
  p: TRttiProperty;
begin
  t := ctx.GetType(TypeInfo(TMyRecord));
  if Assigned(t) then
  begin
    for f in t.GetFields do
    begin
      if f.Visibility in [mvPublic..mvPublished] then
        Writeln(f.Name + ' = ' + f.GetValue(@Item).ToString);
    end;

    for p in t.GetProperties do
    begin
      if p.Visibility in [mvPublic..mvPublished] then
        Writeln(p.Name + ' = ' + p.GetValue(@Item).ToString);
    end;
  end;
end;

Also welchen Pointer gibt man bei
Delphi-Quellcode:
p.GetValue(@Item).ToString
an ?

mit p.name komm ich zwar an die Propertienamen, jedoch nich an den Wert.
nagut p.name tuts auch schon =)

DeddyH 15. Aug 2011 10:26

AW: TList generische Liste Fehler beim deklarieren RTTI
 
Es steht ja beinahe schon da. Trotzdem hier noch ein Beispiel mit einer Klasse statt eines Records (Code von Stevie weitestgehend übernommen, ein Button und ein Memo auf dem Formular):
Delphi-Quellcode:
uses RTTI, TypInfo;

type
  TTestClass = class
  private
    FSomeString: string;
    FSomeInteger: integer;
    FSomeDouble: double;
  public
    property SomeString: string read FSomeString write FSomeString;
    property SomeInteger: integer read FSomeInteger write FSomeInteger;
    property SomeDouble: double read FSomeDouble write FSomeDouble;
  end;

procedure TForm1.Button1Click(Sender: TObject);
var
  Test: TTestClass;
  ctx: TRttiContext;
  t: TRttiType;
  p: TRttiProperty;
begin
  Test := TTestClass.Create;
  try
    Test.SomeString := 'Hallo Welt';
    Test.SomeInteger := 42;
    Test.SomeDouble := Pi;
    t := ctx.GetType(TypeInfo(TTestClass));
    if Assigned(t) then
      for p in t.GetProperties do
        begin
          if p.Visibility in [mvPublic..mvPublished] then
            Memo1.Lines.Add(p.Name + ' = ' + p.GetValue(Test).ToString);
        end;
  finally
    Test.Free;
  end;
end;

H3llsing 15. Aug 2011 10:32

AW: TList generische Liste Fehler beim deklarieren RTTI
 
Vielen dank,
ich hab die klammern falsch gesetzt :(
Delphi-Quellcode:
p.GetValue(Tzuordnung.ToString)

DeddyH 15. Aug 2011 10:34

AW: TList generische Liste Fehler beim deklarieren RTTI
 
Ist das eine class property? Sonst wäre TZuordnung vermutlich falsch, sondern es muss Zuordnung heißen, der Wert steht ja in der Eigenschaft der Instanz und nicht der Klasse.

H3llsing 15. Aug 2011 10:40

AW: TList generische Liste Fehler beim deklarieren RTTI
 
nein ist keine Klassen-Property also Instanz.
Aber das ganze ist eine Procedure der Klasse Tzuordnung und ich möchte auf die momentane Instanz zugreifen.

mit Tzuordnung krachts beim 2ten durchlauf und bei Zuordnung sagt er undefinierter bezeichner

Hier die Procedure
Sie fügt die bereits gesetzten Verbidungen aus der DB in die Tvs als Unterknoten ein.
Delphi-Quellcode:
procedure TZuordnung.ladeVerbindungen(TV_ZO,TV_DB:ttreeview);
var
  MyIterator : TStringDivideIterator;
  i: Integer;
  ctx: TRttiContext;
  t: TRttiType;
  f: TRttiField;
  p: TRttiProperty;
  ParentNode : Ttreenode;
  CNode : Ttreenode;

  ndx     :integer;
begin
  ndx := 0;
  ParentNode := TV_DB.Items.GetFirstNode;
  t := ctx.GetType(TypeInfo(Tzuordnung));
  if Assigned(t) then
  begin
    for p in t.GetProperties do
    begin
      if p.Visibility in [mvPublic..mvPublished] then
      begin
        MyIterator := TStringDivideIterator.Create;
        try
          MyIterator.Pattern := ';';
          MyIterator.Text := p.GetValue(Tzuordnung).ToString;

          While MyIterator.MoveNext do
          begin
            if(ndx > 3)then
            begin
              CNode := TV_DB.Items.AddChildObject(ParentNode,MyIterator.CurrentStr,nil);
              CNode.ImageIndex   := -1;
              CNode.SelectedIndex := -1;
              //hier noch andern baum adden
              for i:=0 to TV_ZO.items.count-1 do
              if TV_ZO.Items.Item[i].Text=MyIterator.CurrentStr then
              begin
                CNode := TV_ZO.Items.AddChildObject(TV_ZO.Items.Item[i],ParentNode.Text,nil);
                CNode.ImageIndex:=-1;
                CNode.SelectedIndex := -1;
                CNode.Parent.ImageIndex := 1;
              end;

              ParentNode.ImageIndex := 1;
              ParentNode.SelectedIndex := 2;
            end;
          end;
          if(ndx > 3)then
          ParentNode := ParentNode.getNextSibling;

        finally
          MyIterator.Free;
        end;
        inc(ndx);
      end;
    end;
  end;
  TV_ZO.FullExpand;
  TV_db.FullExpand;
end;

DeddyH 15. Aug 2011 10:47

AW: TList generische Liste Fehler beim deklarieren RTTI
 
Hast Du es mal mit self versucht?

H3llsing 15. Aug 2011 10:52

AW: TList generische Liste Fehler beim deklarieren RTTI
 
:wall:
ja danke.. ich glaub es ist manchmal besser wenn man sich nur auf 1 Projekt konzentriert.
Dann versucht mans nicht mit THIS und wundert sich warums nich geht in delphi ;D


Vielen Dank nochmal an euch beide! Habt mir sehr geholfen mit dem Umgang von Klassen in Delphi!
Das zeigt wiedermal was für nette Comunity das hier doch ist =D

Stevie 15. Aug 2011 13:22

AW: TList generische Liste Fehler beim deklarieren RTTI
 
Ich würde diesen Code übrigens nicht in die Klasse packen, denn damit hast du eine direkte Abhängigkeit auf deine Controlklasse -> nicht gut.

Warum nicht gut? Stell dir vor, du brauchst diese Klasse nur als Datenobjekt in einem Projekt, welches nichts mit Benutzeroberfläche zu tun hat. Dann wird trotzdem die VCL gebraucht.


Alle Zeitangaben in WEZ +1. Es ist jetzt 06:43 Uhr.

Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz