AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Zurück Delphi-PRAXiS Programmierung allgemein Programmieren allgemein EListError, warum? ObjectList mit Daten füllen
Thema durchsuchen
Ansicht
Themen-Optionen

EListError, warum? ObjectList mit Daten füllen

Ein Thema von delphifan2004 · begonnen am 20. Mai 2022 · letzter Beitrag vom 24. Mai 2022
Antwort Antwort
Seite 1 von 2  1 2      
delphifan2004

Registriert seit: 26. Nov 2004
Ort: Dresden
266 Beiträge
 
Delphi 10.3 Rio
 
#1

EListError, warum? ObjectList mit Daten füllen

  Alt 20. Mai 2022, 14:46
Wie kann ich Daten in eine Stringliste korrekt übernehmen?

Ich will die Grid Komponente mal selber nachbauen.

Ich habe folgenden Code:

Delphi-Quellcode:
procedure TCustomGrid.Paint;
var ACol,ARow,w,h,l,t,r,b: Integer;
begin
  inherited Paint;
  for ARow:=0 to FRowsContainer.Count-1 do
  for ACol:=0 to TStringList(FRowsContainer.Items[ARow]).Count-1 do
  begin
    w := TGridColumn(TStringList(FRowsContainer.Items[ARow]).Objects[ACol]).Width;
    h := TGridColumn(TStringList(FRowsContainer.Items[ARow]).Objects[ACol]).Height;
    l := TGridColumn(TStringList(FRowsContainer.Items[ARow]).Objects[ACol]).Left;
    t := TGridColumn(TStringList(FRowsContainer.Items[ARow]).Objects[ACol]).Top;

    DrawRectangleClip(vscreen,l,t,l+w,t+h,ToColor(colBlack));

    t := t + h;
    l := l + w;
  end;
end;
Der Create Konstruktor sieht so aus:

Delphi-Quellcode:
constructor TCustomGrid.Create(AOwner: TComponent);
begin
  inherited Create(AOwner);
  FRowsContainer := TObjectList.Create;
  FRowsContainer.Capacity := 10;
  FColsContainer := TStringList.Create; //wird gar nicht benötigt, kann aber zum Speichern zusätzlicher Infos verwendet werden
  FColsContainer.Capacity := 5;
  ClipRect := Rect(0,0,600,36);
  FHeight := ClipRect.Bottom - ClipRect.Top;
  FWidth := ClipRect.Right - ClipRect.Left;
  FRowHeight := 26;
  FColWidth := 60;
  CreateRows(9);
  CreateCols(5);
  FFixedCols := 0;
  FFixedRows := 0;
end;

procedure TCustomGrid.CreateCols(Count: Integer);
begin
  SetCols(Count);
end;

procedure TCustomGrid.CreateRows(Count: Integer);
begin
  SetRows(Count);
end;

procedure TCustomGrid.SetRows(AValue: Integer); //Zuerst SetRows, danach SetCols
var ARow: Integer; AList: TStringList;
begin
  if FRows=AValue then Exit;
  FRows:=AValue;
  for ARow := 0 to FRows-1 do
  begin
    AList := TStringList.Create; AList.Capacity := 5;
    FRowsContainer.Add(AList);
  end;
end;

procedure TCustomGrid.SetCols(AValue: Integer); //Passiert am Anfang vor Benutzung des Grids
var ACol,ARow: Integer;
begin
  if FCols=AValue then Exit;
  FCols:=AValue;
  for ARow := 0 to FRowsContainer.Count -1 do
  begin
    for ACol := 0 to FCols-1 do TStringList(FRowsContainer.Items[ARow]).AddObject(' ', TGridColumn.Create(self));
    TGridColumn(TStringList(FRowsContainer.Items[ARow]).Objects[ACol]).Width := FColWidth;
    TGridColumn(TStringList(FRowsContainer.Items[ARow]).Objects[ACol]).Height := FRowHeight;
  end;
end;
Die relevanten Datenstrukturen sind wie folgt, definiert:

Das Grid enhält in einer Stringliste die Spaltenstrings, in Objects eine TGridColumn mit allen Daten. Eine TObjectList nimmt je Zeile dann eine TStringList auf, deren Strings die
Spalten bilden, sofern die Spalteninhalte Strings sind oder bei Integer oder Double Werten die String Repräsentation dieser Werte.

Delphi-Quellcode:
  { TGridColDimension }

  TGridColDimension = record
    Height: Integer;
    Width: Integer;
  end;

  TGridDataItem = record
    Dimension: TGridColDimension;
    Field: TObject; //Für ein TField Objekt
    //Fieldnum: Integer;
    case Longword of
     0: (BinData : TObject); //Binärdaten aufnehmen
     1: (Contents: Longword);
     2: (Int32Val: Integer);
     3: (FloatVal: Double);
     4: (Int16Val: smallint);
  end;

  { TGridGenericItem }

  TGridGenericItem = class(TObject)
  private
    FGridData: TGridDataItem;
    function GetGridData: TGridDataItem;
    procedure SetGridData(AValue: TGridDataItem);
  public

    constructor Create;
    constructor Create(AData: TObject);
    destructor Destroy; override;
    property GridData: TGridDataItem read GetGridData write SetGridData;

  end;

  { TGridColumn }

  TGridColumn = class(TBaseControl)
  private
    FItem: TGridGenericItem;
    FLeft: Integer;
    FTop: Integer;
    function GetContent: TGridGenericItem;
    function GetWidth: Integer;
    function GetHeight: Integer;
    procedure SetContent(AValue: TGridGenericItem);
    procedure SetLeft(AValue: Integer);
    procedure SetTop(AValue: Integer);
    procedure SetWidth(AValue: Integer);
    procedure SetHeight(AValue: Integer);
  public
    constructor Create(AOwner: TComponent);
    destructor Destroy; override;
    procedure Paint; override;
    property Content: TGridGenericItem read GetContent write SetContent;
    property Left: Integer read FLeft write SetLeft;
    property Top: Integer read FTop write SetTop;
    property Width: Integer read GetWidth write SetWidth;
    property Height: Integer read GetHeight write SetHeight;
  end;

  { TCustomGrid }

  TCustomGrid = class(TBaseControl)
  private
    FCols: Integer;
    FFixedCols: Integer;
    FFixedRows: Integer;
    FRows: Integer;
    FColsContainer: TStrings; //in Objects[Index] -> TGridGenericItem
    FRowsContainer: TObjectList;
    FRowHeight: Integer;
    FColWidth: Integer;
    function GetCells(X, Y: Integer): String;
    function GetColHeights(Index: Integer): Integer;
    function GetColWidths(Index: Integer): Integer;
    function GetItems(X,Y: Integer): TGridColumn;
    procedure SetCells(X, Y: Integer; AValue: String);
    procedure SetColHeights(Index: Integer; AValue: Integer);
    procedure SetCols(AValue: Integer);
    procedure SetColWidth(AValue: Integer);
    procedure SetColWidths(Index: Integer; AValue: Integer);
    procedure SetFixedCols(AValue: Integer);
    procedure SetFixedRows(AValue: Integer);
    procedure SetItems(X,Y: Integer; AValue: TGridColumn);
    procedure SetRowHeight(AValue: Integer);
    procedure SetRows(AValue: Integer);
  public
    constructor Create(AOwner: TComponent);
    destructor Destroy; override;
    procedure AddRow;
    procedure CreateCols(Count: Integer);
    procedure CreateRows(Count: Integer);
    procedure Paint; override;
    property Cells[X,Y: Integer]: String read GetCells write SetCells;
    property Cols: Integer read FCols write SetCols; //Anzahl Spalten. Count of columns.
    property Rows: Integer read FRows write SetRows; //Anzahl Zeilen. Count of rows.
    property FixedCols: Integer read FFixedCols write SetFixedCols; //for column title
    property FixedRows: Integer read FFixedRows write SetFixedRows; //for row title
    property Items[X,Y: Integer]: TGridColumn read GetItems write SetItems; //Inhalte der Zellen, in cells immer als String, hier aber die realen Werte
    property RowHeight: Integer read FRowHeight write SetRowHeight;
    property ColWidth: Integer read FColWidth write SetColWidth;
    property ColHeights[Index: Integer]: Integer read GetColHeights write SetColHeights; //Rückgabetyp noch überlegen
    property ColWidths[Index: Integer]: Integer read GetColWidths write SetColWidths;
  end;

Was mache ich mit der Stringliste falsch?


Ich bekommen einen EListError, der mir als Meldung die letzte Zeile der Objektliste FRowsContainer anzeigt. Warum. Wie kann ich dieses Problem elegant umgehen?

Geändert von delphifan2004 (20. Mai 2022 um 14:49 Uhr)
  Mit Zitat antworten Zitat
venice2
(Gast)

n/a Beiträge
 
#2

AW: EListError, warum? ObjectList mit Daten füllen

  Alt 20. Mai 2022, 15:21
Habe jetzt nicht nach deinen fehler gesucht aber könnte man das nicht auch so schreiben?
Delphi-Quellcode:
    t := t + h;
    l := l + w;
Delphi-Quellcode:
    inc(t, h);
    inc(l, w);
  Mit Zitat antworten Zitat
Benutzerbild von Uwe Raabe
Uwe Raabe

Registriert seit: 20. Jan 2006
Ort: Lübbecke
11.015 Beiträge
 
Delphi 12 Athens
 
#3

AW: EListError, warum? ObjectList mit Daten füllen

  Alt 20. Mai 2022, 15:41
Warum überhaupt dieses Hochzählen, wo die Werte doch im nächsten Durchlauf wieder gesetzt werden?
Uwe Raabe
Certified Delphi Master Developer
Embarcadero MVP
Blog: The Art of Delphi Programming
  Mit Zitat antworten Zitat
venice2
(Gast)

n/a Beiträge
 
#4

AW: EListError, warum? ObjectList mit Daten füllen

  Alt 20. Mai 2022, 16:07
Warum überhaupt dieses Hochzählen, wo die Werte doch im nächsten Durchlauf wieder gesetzt werden?
dein Einwand ist berechtigt.

EDIT:
Eventuell so wenn t und l global definiert sind.

Delphi-Quellcode:
    l := l + TGridColumn(TStringList(FRowsContainer.Items[ARow]).Objects[ACol]).Left;
    t := t + TGridColumn(TStringList(FRowsContainer.Items[ARow]).Objects[ACol]).Top;

    inc(t, h);
    inc(l, w);

Geändert von venice2 (20. Mai 2022 um 16:25 Uhr)
  Mit Zitat antworten Zitat
Incocnito

Registriert seit: 28. Nov 2016
210 Beiträge
 
#5

AW: EListError, warum? ObjectList mit Daten füllen

  Alt 20. Mai 2022, 16:19
Moin,

vielleicht solltest du ein kleines Test-Programm posten, dann kann man das auch leichter testen.

Was mir komisch vorkommt, so beim ersten drüber schauen (neben dem von Uwe Raabe), dass
du in den Methoden SetRows und SetCols die Liste von 0 bis zur gewünschten neuen Zeilenzahl (um mal bei SetRows zu bleiben)
füllst. Wird das aber ein zweites mal aufgerufen leerst du die derzeitige Liste nicht,
bzw. füllst nur noch den neuen Anteil auf.

Als zweites würde ich in der geschachtelten Forschleife TStringList(FRowsContainer.Items[ARow])
zwischenspeichern ... das macht das Ganze etwas lesbarer meiner Meinung nach.
Außerdem kannst du dann auch leicht in Delphi beim Debuggen in die StingrListe rein schauen,
was auch hilfreich sein kann.

Als drittes fehlt in SetCols in der inneren For-Schleife das begin-end, wodurch nur
die eine Zeile ausgeführt wird.
Auch hier wieder mein Appell: Macht auch für einzeilige Sachen bei bedingungen (if) oder schleifen (for, while, ...)
IMMER begin-end. Du bist nicht der erste der solch einen Fehler hat.
Das klang jetzt negativer als es gemeint war. Bitte nicht negativ lesen! 😅

Ich hoffe das hilft etwas.

Liebe Grüße
Incocnito
  Mit Zitat antworten Zitat
delphifan2004

Registriert seit: 26. Nov 2004
Ort: Dresden
266 Beiträge
 
Delphi 10.3 Rio
 
#6

AW: EListError, warum? ObjectList mit Daten füllen

  Alt 20. Mai 2022, 16:23
Warum überhaupt dieses Hochzählen, wo die Werte doch im nächsten Durchlauf wieder gesetzt werden?
Weil t=top ist und irgendwie die Höhe der Zeile her muss. Aber ok, dennoch danke für den Hinweis, ich guck mir den Code noch mal an, vielleicht geht das eleganter zu lösen. Ich brauche auf jeden Fall das aktuelle Top und die Höhe der Zeile.

Aber warum bekomme ich den EListError? Und wie kann ich den bei solchen Listen ein für allemal umgehen, den hatte ich schon mehrfach mit Listen?
  Mit Zitat antworten Zitat
venice2
(Gast)

n/a Beiträge
 
#7

AW: EListError, warum? ObjectList mit Daten füllen

  Alt 20. Mai 2022, 16:25
Zitat:
Weil t=top ist und irgendwie die Höhe der Zeile her muss.
Siehe mein Edit.

Geändert von venice2 (20. Mai 2022 um 16:32 Uhr)
  Mit Zitat antworten Zitat
Benutzerbild von Uwe Raabe
Uwe Raabe

Registriert seit: 20. Jan 2006
Ort: Lübbecke
11.015 Beiträge
 
Delphi 12 Athens
 
#8

AW: EListError, warum? ObjectList mit Daten füllen

  Alt 20. Mai 2022, 16:30
Aber warum bekomme ich den EListError?
Könnte es sein, dass hier die beiden letzten Zeilen noch in die For-Schleife gehören und da lediglich ein Begin/End fehlt? (Der Compiler sollte eine Warnung liefern!)
Delphi-Quellcode:
    for ACol := 0 to FCols-1 do TStringList(FRowsContainer.Items[ARow]).AddObject(' ', TGridColumn.Create(self));
    TGridColumn(TStringList(FRowsContainer.Items[ARow]).Objects[ACol]).Width := FColWidth;
    TGridColumn(TStringList(FRowsContainer.Items[ARow]).Objects[ACol]).Height := FRowHeight;
Besser wäre aber das ganze wie oben schon erwähnt mit einer lokalen Variable zu lösen:
Delphi-Quellcode:
    for ACol := 0 to FCols-1 do begin
      var gridColumn := TGridColumn.Create(self);
      gridColumn.Width := FColWidth;
      gridColumn.Height := FRowHeight;
      TStringList(FRowsContainer.Items[ARow]).AddObject(' ', gridColumn);
    end;
Uwe Raabe
Certified Delphi Master Developer
Embarcadero MVP
Blog: The Art of Delphi Programming
  Mit Zitat antworten Zitat
delphifan2004

Registriert seit: 26. Nov 2004
Ort: Dresden
266 Beiträge
 
Delphi 10.3 Rio
 
#9

AW: EListError, warum? ObjectList mit Daten füllen

  Alt 20. Mai 2022, 17:57
Aber warum bekomme ich den EListError?
Könnte es sein, dass hier die beiden letzten Zeilen noch in die For-Schleife gehören und da lediglich ein Begin/End fehlt? (Der Compiler sollte eine Warnung liefern!)
Delphi-Quellcode:
    for ACol := 0 to FCols-1 do TStringList(FRowsContainer.Items[ARow]).AddObject(' ', TGridColumn.Create(self));
    TGridColumn(TStringList(FRowsContainer.Items[ARow]).Objects[ACol]).Width := FColWidth;
    TGridColumn(TStringList(FRowsContainer.Items[ARow]).Objects[ACol]).Height := FRowHeight;
Besser wäre aber das ganze wie oben schon erwähnt mit einer lokalen Variable zu lösen:
Delphi-Quellcode:
    for ACol := 0 to FCols-1 do begin
      var gridColumn := TGridColumn.Create(self);
      gridColumn.Width := FColWidth;
      gridColumn.Height := FRowHeight;
      TStringList(FRowsContainer.Items[ARow]).AddObject(' ', gridColumn);
    end;
OK, danke, ist geändert, allerdings habe ich den EListError immer noch. Irgendwas Anderes ist da noch verkehrt. Ich sehe aber nicht, was, vielleicht sollte ich für heute aufhören und Abstand gewinnen und übers WE noch mal schauen.
  Mit Zitat antworten Zitat
Delphi.Narium

Registriert seit: 27. Nov 2017
2.418 Beiträge
 
Delphi 7 Professional
 
#10

AW: EListError, warum? ObjectList mit Daten füllen

  Alt 20. Mai 2022, 19:07
Zitat von delphifan2004:
Ich bekommen einen EListError, der mir als Meldung die letzte Zeile der Objektliste FRowsContainer anzeigt.
Und welche Zeile genau ist das?

Die letzte im Eingangspost oder die letzte in welcher der Prozeduren?

Zitat:
EListError is the exception class for list and string errors.

EListError is raised when an error is made in a list, TStrings, or TStringList object. This exception commonly occurs when an application refers to an item that is out of the list's range.

EListError also occurs if an application tries to add a duplicate string to a TStringList object when the value of the Duplicates property is dupError.

An EListError exception is raised when an application attempts to insert a string into a sorted string list, since the insertion of a string at a specified position may put the list out of order.
Welche Variante des Fehler EListError kommt denn hier in Frage?

Ein Fehler, der durch nicht ganz korrekte Zählweise entstehen könnte oder die Variante, dass da irgendwo eine Dublette in 'ner Stringliste eingefügt wird?

Bei Zählfehlern könnte man ggfls. hier im Forum behilflich sein, wenn die exakte Fehlerzeile mal bekanntgegeben wird. Einen potentiellen Dublettenfehler können wir so ohne weiteres nicht erkennen. Weder kennen wir die zu verarbeitenden Daten noch wissen wir, ob die Stringlisten sortiert sein könnten und das Einfügen von Dubletten eventuell nicht möglich ist.

Die dritte Variante könnte eintreten, wenn bei einer Liste, deren AList.Capacity := 5; ist, das sechste Element eingefügt wird.
Hier könnte ggfls. ein SetCols(6); (oder ein beliebiger anderer Wert > 5?) Fehlerursache sein.

Oder ich könnte mit meinen Mutmaßungen auch vollständig daneben liegen
  Mit Zitat antworten Zitat
Antwort Antwort
Seite 1 von 2  1 2      


Forumregeln

Es ist dir nicht erlaubt, neue Themen zu verfassen.
Es ist dir nicht erlaubt, auf Beiträge zu antworten.
Es ist dir nicht erlaubt, Anhänge hochzuladen.
Es ist dir nicht erlaubt, deine Beiträge zu bearbeiten.

BB-Code ist an.
Smileys sind an.
[IMG] Code ist an.
HTML-Code ist aus.
Trackbacks are an
Pingbacks are an
Refbacks are aus

Gehe zu:

Impressum · AGB · Datenschutz · Nach oben
Alle Zeitangaben in WEZ +1. Es ist jetzt 17:22 Uhr.
Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz