[Erledigt] Object in StringGrid mit TFPGObjectList

Für Fragen zur Programmiersprache auf welcher Lazarus aufbaut

[Erledigt] Object in StringGrid mit TFPGObjectList

Beitragvon MacWomble » 16. Jan 2019, 17:31 [Erledigt] Object in StringGrid mit TFPGObjectList

Ich möchte in einem Stringgrid ein Object ablegen und auch wieder auslesen. Dabei bin ich nach Anleitung vor gegangen, wobei ich allerdings das Objekt aus einer TFPGObjectList beziehe. Vermutlich habe ich hier etwas nicht verstanden:

Code: Alles auswählen
procedure TfrmArtikel.btnEditPreisClick(Sender: TObject);
var
  ID: integer;
  P: TArtikelPreis;
begin
  P:= TArtikelPreis(sgPreise.Objects[4, sgPreise.Row]);
  //  Hier will ich mit P arbeiten, also einem Object vom Typ TArtikelPreis 
  Debugln(P.BezPreisgruppe);
  P.Free;
end;       


übergeben habe ich so:
Code: Alles auswählen
 
ArtikelpreisListe: TArtikelPreisListe;
ArtikelpreisListe:= TArtikelPreisListe.Create();
FillArtikelpreisListe;
 
 
...
with sgPreise do
begin     
    RowCount := ArtikelpreisListe.Count;
    for i := 0 to ArtikelpreisListe.Count - 1 do
    begin
    { Zeit  Lohn  Service  Material  Geraet  Fremdleistung   VKNetto   VKBrutto  }
      Cells[0, i] := IntToStr(ArtikelpreisListe.Items[i].ID);
      Cells[1, i] := ArtikelpreisListe.Items[i].BezPreisgruppe;
      Cells[2, i] := ArtikelpreisListe.Items[i].BezMengeneinheit;
      Cells[3, i] := ArtikelpreisListe.Items[i].BezSteuersatz;
// bis hier alles OK
// und jetzt noch das Objekt:
      Objects[0, i] := ArtikelgruppenListe.Items[i];
    end;
end;
FreeAndNil(ArtikelpreisListe);               


Code: Alles auswählen
  TArtikelPreisListe = class(specialize TFPGObjectList<TArtikelPreis>)
  private
 
  public
    function Add(Obj: TArtikelPreis): integer;// override;
    procedure ReadAllData;
    procedure ReadAllByArtikelID(IDArtikel: integer);
    procedure ReadListData(Query: string);
  published
 
  end;   

Ist ArtikelgruppenListe.Items[i] kein Objct des Typs TArtikelPreis?

Wenn ich Warf im Thread zur Combobox richtig verstanden habe, geht das wieder über TypeCast ? - Ich bekomme es nicht hin :oops:
Zuletzt geändert von MacWomble am 17. Jan 2019, 20:48, insgesamt 3-mal geändert.
Alle sagten, dass es unmöglich sei - bis einer kam und es einfach gemacht hat.
MacWomble
Lazarusforum e. V.
 
Beiträge: 795
Registriert: 17. Apr 2008, 00:59
Wohnort: Freiburg
OS, Lazarus, FPC: Mint 19.1 Cinnamon / CodeTyphon LAB Version 6.90 / FP 3.3.1 Rev 42237 | 
CPU-Target: Intel i7 64/32 Bit
Nach oben

Beitragvon Michl » 16. Jan 2019, 18:40 Re: Object in StringGrid mit TFPGObjectList

MacWomble hat geschrieben:
Code: Alles auswählen
      Cells[3, i] := ArtikelpreisListe.Items[i].BezSteuersatz;
// bis hier alles OK
// und jetzt noch das Objekt:
      Objects[0, i] := ArtikelgruppenListe.Items[i];
Bist du sicher, daß du ArtikelgruppenListe und nicht ArtikelpreisListe haben wolltest? Wie sieht denn die Deklaration der ArtikelgruppenListe aus?
Code: Alles auswählen
type
  TLiveSelection = (lsMoney, lsChilds, lsTime);
  TLive = Array[0..1] of TLiveSelection; 
Michl
 
Beiträge: 2320
Registriert: 19. Jun 2012, 11:54
OS, Lazarus, FPC: Win7 Laz 1.7 Trunk FPC 3.1.1 Trunk | 
CPU-Target: 32Bit/64bit
Nach oben

Beitragvon braunbär » 16. Jan 2019, 18:50 Re: Object in StringGrid mit TFPGObjectList

Das erste, was mir auffällt:
Code: Alles auswählen
P:= TArtikelPreis(sgPreise.Objects[4, sgPreise.Row]);

Jetzt ist P ein Zeiger (Klassenvariable sind immer Zeiger auf die eigentlichen Klasseninstanzen) auf eine Klasseninstanz, die in deiner TFPGObjectList gespeichert ist.
Code: Alles auswählen
P.free

Jetzt hast du das Objekt, auf das P gezeigt hat, freigegeben, es ist also das Objekt in der TFPGObjectList freigegeben worden und nicht mehr in der Liste drin, der entsprechende Objects-Pointer ist aber nicht nil (nur der Zeiger p ist hier durch freeandnil =nil gesetzt worden), sondern zeigt immer auf das freigegebene Objekt.. Ich denke, das wolltest du nicht, oder?

P ist nicht eine Kopie des Objekts, sondern nur eine Kopie des Zeigers auf das Objekt.

Das gleiche passiert bei
Code: Alles auswählen
FreeAndNil(ArtikelpreisListe); 

Alle Objekte der Artikelpreisliste werden hier vermutlich freigegeben (abhängig von der Property freeobjects), dadurch zeigen aber die Zeiger, die du in deiner TFPGObjectList gespeichert hast, auch ins Nirwana.
braunbär
 
Beiträge: 286
Registriert: 8. Jun 2017, 17:21

Beitragvon MacWomble » 16. Jan 2019, 20:43 Re: Object in StringGrid mit TFPGObjectList

Michl hat geschrieben:Bist du sicher, daß du ArtikelgruppenListe und nicht ArtikelpreisListe haben wolltest? Wie sieht denn die Deklaration der ArtikelgruppenListe aus?


:oops: :oops: :oops:

Aber es geht trotzdem nicht weiter ...

Mit den Freigaben hast du Recht, aber um diese geht es nicht. Ich will ja dazwischen verarbeiten. Das Objekt lässt sich nicht aus dem Grid lesen, bzw. ist nach dem Auslesen = NIL

Wenn ich dich richtig verstehe ist im Grid nur ein Zeiger. d.h. das Objekt geht verloren, wenn ich die zugrunde liegende Artikelpreisliste freigebe.
Ich werde das nachher mal testen, das wäre eine für mich verständliche und logische Erklärung.
Alle sagten, dass es unmöglich sei - bis einer kam und es einfach gemacht hat.
MacWomble
Lazarusforum e. V.
 
Beiträge: 795
Registriert: 17. Apr 2008, 00:59
Wohnort: Freiburg
OS, Lazarus, FPC: Mint 19.1 Cinnamon / CodeTyphon LAB Version 6.90 / FP 3.3.1 Rev 42237 | 
CPU-Target: Intel i7 64/32 Bit
Nach oben

Beitragvon Michl » 16. Jan 2019, 21:02 Re: Object in StringGrid mit TFPGObjectList

-
Code: Alles auswählen
type
  TLiveSelection = (lsMoney, lsChilds, lsTime);
  TLive = Array[0..1] of TLiveSelection; 
Michl
 
Beiträge: 2320
Registriert: 19. Jun 2012, 11:54
OS, Lazarus, FPC: Win7 Laz 1.7 Trunk FPC 3.1.1 Trunk | 
CPU-Target: 32Bit/64bit
Nach oben

Beitragvon MacWomble » 17. Jan 2019, 00:49 Re: Object in StringGrid mit TFPGObjectList

Danke so weit. Das funktioniert jetzt auch.

... und dann war da noch die Frage aufgetaucht, wie ich in der TFPGObjectList (z.B. in der ArtikelpreisListe) einen Eintrag nach Feldinhalt finden kann.
Muss ich hierfür eine Schleife bemühen, oder gibt es eine Funktion?
Alle sagten, dass es unmöglich sei - bis einer kam und es einfach gemacht hat.
MacWomble
Lazarusforum e. V.
 
Beiträge: 795
Registriert: 17. Apr 2008, 00:59
Wohnort: Freiburg
OS, Lazarus, FPC: Mint 19.1 Cinnamon / CodeTyphon LAB Version 6.90 / FP 3.3.1 Rev 42237 | 
CPU-Target: Intel i7 64/32 Bit
Nach oben

Beitragvon Michl » 17. Jan 2019, 07:57 Re: Object in StringGrid mit TFPGObjectList

Wenn das Objekt bekannt ist, kannst du mit IndexOf dessen Stelle in der Liste zurückgeben lassen.

Wenn du nach Properties deines Objektes suchen willst, musst du dies selber implementieren. Dazu kannst du IndexOf überladen oder eine eigene Suchfunktion implementieren, z.B.:
Code: Alles auswählen
  TArtikelPreisListe = class(specialize TFPGObjectList<TArtikelPreis>)
...
    function IndexOf(AId: Integer): Integer; overload;
    function IndexOf(const ABezPreisgruppe: String): Integer; overload;
  end;
...
function TArtikelPreisListe.IndexOf(AId: Integer): Integer;
var
  i: Integer;
begin
  Result := -1;
  for i := 0 to Count - 1 do
    if AId = TArtikelPreis(Items[i]).ID then  // der Typecast kann weggelassen werden, ist aber zur Codevervollständigung praktisch, siehe unten
      Exit(i);
end;
 
function TArtikelPreisListe.IndexOf(const ABezPreisgruppe: String): Integer;
var
  i: Integer;
begin
  Result := -1;
  for i := 0 to Count - 1 do
    if ABezPreisgruppe = Items[i].BezPreisgruppe then
      Exit(i);
end
Der Compiler kann den generischen Bezeichner Items[i] schon übersetzen. Die Codetools können bisher nur etwas mit TArtikelPreis(Items[i]) anfangen (FPC 3.0.4, Lazarus Trunk). Die Codekomplettierung, Umbenennung Bezeichner usw. funktionieren derzeit nur mit dem Typecast.
Code: Alles auswählen
type
  TLiveSelection = (lsMoney, lsChilds, lsTime);
  TLive = Array[0..1] of TLiveSelection; 
Michl
 
Beiträge: 2320
Registriert: 19. Jun 2012, 11:54
OS, Lazarus, FPC: Win7 Laz 1.7 Trunk FPC 3.1.1 Trunk | 
CPU-Target: 32Bit/64bit
Nach oben

Beitragvon MacWomble » 17. Jan 2019, 09:07 Re: Object in StringGrid mit TFPGObjectList

Wow ! Danke ! :D
Alle sagten, dass es unmöglich sei - bis einer kam und es einfach gemacht hat.
MacWomble
Lazarusforum e. V.
 
Beiträge: 795
Registriert: 17. Apr 2008, 00:59
Wohnort: Freiburg
OS, Lazarus, FPC: Mint 19.1 Cinnamon / CodeTyphon LAB Version 6.90 / FP 3.3.1 Rev 42237 | 
CPU-Target: Intel i7 64/32 Bit
Nach oben

Beitragvon MacWomble » 17. Jan 2019, 10:11 Re: Object in StringGrid mit TFPGObjectList

Mit
Code: Alles auswählen
P := TArtikelPreis(ArtikelpreisListe.items[aIndex]); 


habe ich einen Pointer auf ein Item in der ArtikelpreisListe gesetzt.
Wenn ich nun P andere Werte zuweise, sind diese aber noch nicht in der ArtikelpreisListe sichtbar. (Ich dachte ich verändere so auch das Item, da P nur ein Pointer ist)
Was verstehe ich hier nicht?
Alle sagten, dass es unmöglich sei - bis einer kam und es einfach gemacht hat.
MacWomble
Lazarusforum e. V.
 
Beiträge: 795
Registriert: 17. Apr 2008, 00:59
Wohnort: Freiburg
OS, Lazarus, FPC: Mint 19.1 Cinnamon / CodeTyphon LAB Version 6.90 / FP 3.3.1 Rev 42237 | 
CPU-Target: Intel i7 64/32 Bit
Nach oben

Beitragvon Michl » 17. Jan 2019, 11:12 Re: Object in StringGrid mit TFPGObjectList

Kannst du mal die Deklaration von TArtikelPreis zeigen?
Code: Alles auswählen
type
  TLiveSelection = (lsMoney, lsChilds, lsTime);
  TLive = Array[0..1] of TLiveSelection; 
Michl
 
Beiträge: 2320
Registriert: 19. Jun 2012, 11:54
OS, Lazarus, FPC: Win7 Laz 1.7 Trunk FPC 3.1.1 Trunk | 
CPU-Target: 32Bit/64bit
Nach oben

Beitragvon wp_xyz » 17. Jan 2019, 11:26 Re: Object in StringGrid mit TFPGObjectList

Ich denke, die Grundidee, im StringGrid die Pointer auf die einzelnen Einträge in der Preisliste als Object zu verwenden, ist prinzipiell fehlerträchtig, weil nicht sichergestellt ist, dass Grid und Preisliste up-to-date sind. Z.B. kann das Grid einen Eintrag löschen kann, ohne dass die Preisliste das mitkriegt, und umgekehrt. Ich würde stattdessen die ArtikelPreis-Objekte nur in der Preisliste aufführen und für die Ausgabe ein DrawGrid verwenden, anstatt eines StringGrids. Das DrawGrid holt sich die anzuzeigenden Texte aus der Preiseliste. Etwa so wie ich das in dem angehängten Beispiel realisiert habe. Zusätzlich könntest du die Liste noch mit einem OnChange-Event ausstatten, in das sich das Grid einhängt um sich bei einer Änderung der Listeneinträge neu zu zeichnen.
Du hast keine ausreichende Berechtigung, um die Dateianhänge dieses Beitrags anzusehen.
Zuletzt geändert von wp_xyz am 17. Jan 2019, 11:38, insgesamt 1-mal geändert.
wp_xyz
 
Beiträge: 2918
Registriert: 8. Apr 2011, 08:01

Beitragvon MacWomble » 17. Jan 2019, 11:34 Re: Object in StringGrid mit TFPGObjectList

Michl hat geschrieben:Kannst du mal die Deklaration von TArtikelPreis zeigen?


anbei die unit
Du hast keine ausreichende Berechtigung, um die Dateianhänge dieses Beitrags anzusehen.
Alle sagten, dass es unmöglich sei - bis einer kam und es einfach gemacht hat.
MacWomble
Lazarusforum e. V.
 
Beiträge: 795
Registriert: 17. Apr 2008, 00:59
Wohnort: Freiburg
OS, Lazarus, FPC: Mint 19.1 Cinnamon / CodeTyphon LAB Version 6.90 / FP 3.3.1 Rev 42237 | 
CPU-Target: Intel i7 64/32 Bit
Nach oben

Beitragvon MacWomble » 17. Jan 2019, 11:51 Re: Object in StringGrid mit TFPGObjectList

wp_xyz hat geschrieben:Ich denke, die Grundidee, im StringGrid die Pointer auf die einzelnen Einträge in der Preisliste als Object zu verwenden, ist prinzipiell fehlerträchtig, weil nicht sichergestellt ist, dass Grid und Preisliste up-to-date sind. Z.B. kann das Grid einen Eintrag löschen kann, ohne dass die Preisliste das mitkriegt, und umgekehrt. Ich würde stattdessen die ArtikelPreis-Objekte nur in der Preisliste aufführen und für die Ausgabe ein DrawGrid verwenden, anstatt eines StringGrids. Das DrawGrid holt sich die anzuzeigenden Texte aus der Preiseliste. Etwa so wie ich das in dem angehängten Beispiel realisiert habe.


Danke für die Hinweise und die Demo, ich schau mir das an und versuche auch hieraus zu lernen.

Genau in der von dir geäußerten Kritik liegt auch eines meiner Probleme. Ich bekomme die Preise in der Datenbank aktualisiert, aber wenn ich dann das StringGrid wieder neu bestücke (aus ArtikelPreisliste), habe ich immer noch die alten Daten. Da zeigt sich schon die Unzuverlässigkeit meiner Lösung. Die Artikelpreisliste möchte ich aber nach Möglichkeit nicht andauernd neu aus der Datenbank lesen.

Was ich machen möchte:
Im (Wieauchimmer-)Grid wird eine Zeile selektiert. Das damit in Zusammenhang stehende Objekt soll über eine Procedure an die Bearbeitungsmaske gereicht, bearbeitet und zurück gegeben werden. Wenn ich das richtig interpretiert habe, macht Deine Demo genau diese (Habe es mir nur kurz angesehen, komme erst nachmittags dazu)

Ich bin ja noch ganz am Anfang und mache meine ersten bewussten Schritte mit Objekten und Objektlisten. Da ich mein Mammutprojekt umstellen möchte, habe ich mit den einfacheren Sachen (Artikel und Preis und ein paar Listen für Comboboxen) begonnen. So nach und nach kommen dann weitere Sachen dazu. Ich denke, wenn ich die Grundlagen mal verstanden habe, ergibt sich der Rest. Ich habe jedenfalls - dank euch - bereits extrem viel in den letzten 7 Tagen dazu gelernt. :shock:, zumindest bilde ich mir das ein. :oops: :D
Alle sagten, dass es unmöglich sei - bis einer kam und es einfach gemacht hat.
MacWomble
Lazarusforum e. V.
 
Beiträge: 795
Registriert: 17. Apr 2008, 00:59
Wohnort: Freiburg
OS, Lazarus, FPC: Mint 19.1 Cinnamon / CodeTyphon LAB Version 6.90 / FP 3.3.1 Rev 42237 | 
CPU-Target: Intel i7 64/32 Bit
Nach oben

Beitragvon Michl » 17. Jan 2019, 12:03 Re: Object in StringGrid mit TFPGObjectList

MacWomble hat geschrieben:Mit
Code: Alles auswählen
P := TArtikelPreis(ArtikelpreisListe.items[aIndex]); 


habe ich einen Pointer auf ein Item in der ArtikelpreisListe gesetzt.
Wenn ich nun P andere Werte zuweise, sind diese aber noch nicht in der ArtikelpreisListe sichtbar. (Ich dachte ich verändere so auch das Item, da P nur ein Pointer ist)
Was verstehe ich hier nicht?
P ist gemäß obrigen Code und der Deklaration eine Instanz der Klasse TArtikelPreis. Ich hab keine Ahnung warum das nicht gehen sollte.

+1 zu wp seinem Hinweis!!

PS: Ich würde statt P einen Bezeichner wie ArtikelPreis, AArtikelPreis oder LArtikelPreis wählen.
Code: Alles auswählen
type
  TLiveSelection = (lsMoney, lsChilds, lsTime);
  TLive = Array[0..1] of TLiveSelection; 
Michl
 
Beiträge: 2320
Registriert: 19. Jun 2012, 11:54
OS, Lazarus, FPC: Win7 Laz 1.7 Trunk FPC 3.1.1 Trunk | 
CPU-Target: 32Bit/64bit
Nach oben

Beitragvon wp_xyz » 17. Jan 2019, 12:10 Re: Object in StringGrid mit TFPGObjectList

Das mit der Datenbank lese ich hier zum ersten Mal. Dann wäre DBGrid genau das richtige. Es verhält sich etwa genauso, wie mein DrawGrid mache. Es enthält selbst keine Daten, sondern holt sie sich aus der Datenbank. Anders beim StringGrid, das die Daten direkt enthält, und die Daten im StringGrid sind Strings, der zusätzliche Objects-Pointer ist eine Krücke, um dieses Grid etwas flexibler zu machen.

Was stört dich daran, die Preisliste "dauernd" aus der Datenbank eingelesen zu haben? Ob die Daten der Preisliste in einem TDataset liegen oder einer TObjectList oder einem Array, ist doch egal.

MacWomble hat geschrieben:in der von dir geäußerten Kritik[...]
Ich will niemanden "kritisieren"...
wp_xyz
 
Beiträge: 2918
Registriert: 8. Apr 2011, 08:01

» Weitere Beiträge siehe nächste Seite »
Nächste

Zurück zu Freepascal



Wer ist online?

Mitglieder in diesem Forum: 0 Mitglieder und 4 Gäste

porpoises-institution
accuracy-worried