![]() |
EListError, warum? ObjectList mit Daten füllen
Wie kann ich Daten in eine Stringliste korrekt übernehmen?
Ich will die Grid Komponente mal selber nachbauen. Ich habe folgenden Code:
Delphi-Quellcode:
Der Create Konstruktor sieht so aus:
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;
Delphi-Quellcode:
Die relevanten Datenstrukturen sind wie folgt, definiert:
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; 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? |
AW: EListError, warum? ObjectList mit Daten füllen
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); |
AW: EListError, warum? ObjectList mit Daten füllen
Warum überhaupt dieses Hochzählen, wo die Werte doch im nächsten Durchlauf wieder gesetzt werden?
|
AW: EListError, warum? ObjectList mit Daten füllen
Zitat:
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); |
AW: EListError, warum? ObjectList mit Daten füllen
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 |
AW: EListError, warum? ObjectList mit Daten füllen
Zitat:
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? |
AW: EListError, warum? ObjectList mit Daten füllen
Zitat:
|
AW: EListError, warum? ObjectList mit Daten füllen
Zitat:
Delphi-Quellcode:
Besser wäre aber das ganze wie oben schon erwähnt mit einer lokalen Variable zu lösen:
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;
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; |
AW: EListError, warum? ObjectList mit Daten füllen
Zitat:
|
AW: EListError, warum? ObjectList mit Daten füllen
Zitat:
Die letzte im Eingangspost oder die letzte in welcher der Prozeduren? Zitat:
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
Delphi-Quellcode:
ist, das sechste Element eingefügt wird.
AList.Capacity := 5;
Hier könnte ggfls. ein
Delphi-Quellcode:
(oder ein beliebiger anderer Wert > 5?) Fehlerursache sein.
SetCols(6);
Oder ich könnte mit meinen Mutmaßungen auch vollständig daneben liegen ;-) |
AW: EListError, warum? ObjectList mit Daten füllen
Huch! Doublette!
Wie macht delphi das in seinem Stringgrid? Ich codiere:
Delphi-Quellcode:
Und da ist sie, die Doublette! Trotz AList.Duplicates := dupAccept in SetRows! tritt jetzt der Feler immr noch auf, allerdings verändert, das Programm hängt fest, der EListError erscheint nun nicht mehr, aber das Programm hängt.
TStringList(FRowsContainer.Items[ARow]).AddObject(' ', gridColumn);
Wie macht das Delphi mit der Stringliste die auch dort die Strings aufnimmt? Der Fehler trat zuerst hier auf:
Delphi-Quellcode:
Hier noch mal die ganze Methode:
if (ACol<TStringList(FRowsContainer.Items[ARow]).Capacity) and Assigned(TGridColumn(TStringList(FRowsContainer.Items[ARow]).Objects[ACol])) then
begin w := gc.Width; //TGridColumn(TStringList(FRowsContainer.Items[ARow]).Objects[ACol]).Width; //#### Hier der EListError ####[]
Delphi-Quellcode:
Siehe auch Eingangsbeitrag, dortiger Code.
procedure TCustomGrid.Paint;
var ACol,ARow,w,h,l,t,r,b: Integer; gc: TGridColumn; sl: TStringList; rc: TObjectList; begin inherited Paint; for ARow:=0 to FRowsContainer.Count-1 do for ACol:=0 to TStringList(FRowsContainer.Items[ARow]).Count-1 do begin rc := FRowsContainer; sl := TStringList(rc.Items[ARow]); gc := TGridColumn(sl.Objects[ACol]); if (ACol<TStringList(FRowsContainer.Items[ARow]).Capacity) and Assigned(TGridColumn(TStringList(FRowsContainer.Items[ARow]).Objects[ACol])) then begin w := gc.Width; //TGridColumn(TStringList(FRowsContainer.Items[ARow]).Objects[ACol]).Width; //#### Hier der EListError #### h := gc.Height; //TGridColumn(TStringList(FRowsContainer.Items[ARow]).Objects[ACol]).Height; l := gc.Left; //TGridColumn(TStringList(FRowsContainer.Items[ARow]).Objects[ACol]).Left; t := gc.Top; //TGridColumn(TStringList(FRowsContainer.Items[ARow]).Objects[ACol]).Top; end; DrawRectangleClip(vscreen,l,t,l+w,t+h,ToColor(colBlack)); t := t + h; l := l + w; end; end; In SetRows -> AList.Capacity:=5 muss ich natürlich noch anpassen auf beliebig viele Elemente. Aktuell aber sollen für den Test 5 Spalten genügen. Die Schwierigkeit ist hier, dass ich zunächst eine Zeile erzeigen will, aber noch nicht weiß, wie viele Spalten die haben soll, das entscheidet sich danach erst in SetCols(). Ich brauchte hier eine dynamische Anpassung der Spalten nachdem die Zeile erzeugt ist. Auch hier die Frage, wie macht Delphi das in seinem Stringgrid? Da guck ich inzwischen mal in den Code rein. Vielleicht finde ich ja dort die Lösung des Problems. Vorausgesetzt Emba programmiert nicht zu trickreich. :) |
AW: EListError, warum? ObjectList mit Daten füllen
Debuggen ergibt in SetRows die Fortsetzung
for ACol := 0 to FCols-1 do eine Zählung über Spalte 9 hinaus. Warum das? Ich will 9 Spalten haben und nicht 10 SetCols(9)! 0..9 sind doch schon 10 Spalten, FCols -1 sind 9 Spalten! Offenbar wird die Abbruchbedingung nicht eingehalten. Wie kann das sein? Die For Schleife sollte doch automatisch weiter zählen und bei Erreichen des Maximalwertes abbrechen. Ich habe in SetCols() die Zeile if ACol >= FCols-1 then break ergänzt. |
AW: EListError, warum? ObjectList mit Daten füllen
Ich verweise nochmals auf diese Bitte.. Mit den Fehlern wie sie aktuell sind.
So können wir leider nur raten. Zitat:
|
AW: EListError, warum? ObjectList mit Daten füllen
Da versuch ich mal ein Testprogramm zu bauen, das aktuelle verwendet noch andere Units, die machen die Suche nur unübersichtlich. Ich baue ein neues Programm nur mit dem Grid.
Wo ist dieses Edit, das ich mir anschauen soll? |
AW: EListError, warum? ObjectList mit Daten füllen
Zitat:
![]() So wie es vorher(aktuell ist) kann es nicht funktionieren.
Delphi-Quellcode:
Du hättest es spätestens bemerkt wenn du über deinen Fehler hinweg gekommen wärst.l := TGridColumn(TStringList(FRowsContainer.Items[ARow]).Objects[ACol]).Left; // left wird l zugewiesen t := TGridColumn(TStringList(FRowsContainer.Items[ARow]).Objects[ACol]).Top; // Top wird t zugewiesen DrawRectangleClip(vscreen,l,t,l+w,t+h,ToColor(colBlack)); // Beide variablen werden nicht verwendet daher gehen diese Zuweisungen auf dieser Basis ins leere. t := t + h; // t wird anschließend incrementiert aber nicht mehr benutzt weil die Variable t nicht global definiert ist und vorher nicht zugewiesen wird. l := l + w; // l wird anschließend incrementiert aber nicht mehr benutzt weil die Variable l nicht global definiert ist und vorher nicht zugewiesen wird. |
AW: EListError, warum? ObjectList mit Daten füllen
In diesem Testprojekt ist der EListerror weg aber von Paint wird nichts ausgegeben nur die Zeile "Zurück mit << ENTER > >> ...'
Delphi-Quellcode:
@venice2:
program Project3;
{$APPTYPE CONSOLE} {$R *.res} uses System.SysUtils,System.Classes,Contnrs; type TGridColumn = class(Tobject) private FWidth: Integer; FHeight: Integer; public constructor Create; property Width: Integer read FWidth write FWidth; property Height: Integer read FHeight write FHeight; end; TCustomGrid = class(TObject) private FCols: Integer; FRows: Integer; FRowsContainer: TObjectList; procedure SetCols(AValue: Integer); procedure SetRows(AValue: Integer); public constructor Create; destructor Destroy; override; procedure Paint; property Cols: Integer read FCols write SetCols; property Rows: Integer read FRows write SetRows; end; { TGridColumn } constructor TGridColumn.Create; begin inherited Create; end; { TCustomGrid } constructor TCustomGrid.Create; begin inherited Create; FRowsContainer := TObjectList.Create; end; destructor TCustomGrid.Destroy; begin FRowsContainer.Free; inherited; end; procedure TCustomGrid.SetCols(AValue: Integer); var ACol,ARow: Integer; gridColumn: TGridColumn; begin if FCols=AValue then Exit; FCols:=AValue; for ARow := 0 to FRows -1 do begin for ACol := 0 to FCols-1 do begin gridColumn := TGridColumn.Create; gridColumn.Width := 200; gridColumn.Height := 20; TStringList(FRowsContainer.Items[ARow]).AddObject(' ', gridColumn); if ACol >= FCols-1 then break; end; end; end; procedure TCustomGrid.SetRows(AValue: Integer); 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; AList.Duplicates:=dupAccept; FRowsContainer.Add(AList); end; end; procedure TCustomGrid.Paint; var ACol,ARow,w,h,l,t,r,b: Integer; gc: TGridColumn; sl: TStringList; rc: TObjectList; begin for ARow:=0 to FRowsContainer.Count-1 do begin for ACol:=0 to TStringList(FRowsContainer.Items[ARow]).Count-1 do begin rc := FRowsContainer; sl := TStringList(rc.Items[ARow]); gc := TGridColumn(sl.Objects[ACol]); if (ACol<TStringList(FRowsContainer.Items[ARow]).Capacity) and Assigned(gc) then begin w := gc.Width; //TGridColumn(TStringList(FRowsContainer.Items[ARow]).Objects[ACol]).Width; h := gc.Height; //TGridColumn(TStringList(FRowsContainer.Items[ARow]).Objects[ACol]).Height; // l := gc.Left; //TGridColumn(TStringList(FRowsContainer.Items[ARow]).Objects[ACol]).Left; //aus Originalcode übernommen // t := gc.Top; //TGridColumn(TStringList(FRowsContainer.Items[ARow]).Objects[ACol]).Top; //aber hier weggelassen end; // DrawRectangleClip(vscreen,l,t,l+w,t+h,ToColor(colBlack)); writeln('Breite: ',w); //wird nicht angezeigt, warum? writeln('Höhe : ',h); //wird nicht angezeigt, warum? //writeln('Links : ',l); //writeln('Oben : ',t); { t := t + h; //t (Top soll um h (Zeilenhöhe) nach unten, nachdem Gridrahmenlinie oben gezeichnet ist l := l + w; //l (Left) soll um w (Spaltenbreite) nach rechts, nachdem Gridrahmenlinie links gezeichnet ist } inc(t, h); inc(l, w); end; if ARow >= FRows then break; end; end; var Grid: TCustomGrid; begin try { TODO -oUser -cConsole Main : Code hier einfügen } Grid:=TCustomGrid.Create; Grid.Cols := 9; Grid.Rows := 5; Grid.Paint; writeln('Zurück mit << ENTER >> > >>> ... '); readln; except on E: Exception do Writeln(E.ClassName, ': ', E.Message); end; end. Mein Code:
Delphi-Quellcode:
Damit werden doch die Variablen l,t,w und h in der DrawRectangleClip Prozedur verwendet. Aber der EListError verhindert, dass ich dorthin komme.
DrawRectangleClip(vscreen,l,t,l+w,t+h,ToColor(colBlack));
{ t := t + h; l := l + w; } inc(t, h); inc(l, w); end; if ARow >= FRows then break; //Diese Zeile habe ich hinzugefügt, damit nach Zeile 5 keine weitere hinzugefügt wird. Ich weiß zwar, dass die FOR Schleife automatisch abbricht, ja abbrechen sollte, //wenn der Endwert erreicht ist, aber ich habe nun mal den EListError. Übrigens mit Freepascal geschrieben, der Code, aber auch dort ist mir kein Fehler im Compiler bekannt, deshalb habe ich das //bisher nicht erwähnt. l=Left und t=Top werden zwar mit erhöht, aber da sollte ich ddoch wenigstens die erste Gridspalte sehen, so wie der Code hier aussieht. Zitat:
Der von mir gesuchte Fehler muss hier liegen:
Delphi-Quellcode:
Wenn es das ist, wie kann ich solche Zuweisung zuverlässiger erreichen. Schließlich werden auch in meinem Testprojekt Breite und Höhe nicht angezeigt.
rc := FRowsContainer;
sl := TStringList(rc.Items[ARow]); //das hier nicht Assigned oder gc := TGridColumn(sl.Objects[ACol]); //das hier nicht Assigned if (ACol<TStringList(FRowsContainer.Items[ARow]).Capacity) and Assigned(gc) then |
AW: EListError, warum? ObjectList mit Daten füllen
Zitat:
Springt gar nicht erst in deine schleife rein. Prüfe das nochmal..
Delphi-Quellcode:
for ACol:=0 to TStringList(FRowsContainer.Items[ARow]).Count-1 do
Count ist -1 sorry das kann so nichts werden. |
AW: EListError, warum? ObjectList mit Daten füllen
Ok du hast Rows und Cols vertauscht.. deshalb wurde deine TStringliste nicht gefüllt in deinem Beispiel!
Versuche das hier. Habe keinen ElistError läuft wie es soll.
Delphi-Quellcode:
program Project3;
{$APPTYPE CONSOLE} {$R *.res} uses System.SysUtils, System.Classes, Contnrs; type TGridColumn = class(Tobject) private FWidth: Integer; FHeight: Integer; FLeft: Integer; FTop: Integer; public constructor Create; property Width: Integer read FWidth write FWidth; property Height: Integer read FHeight write FHeight; property Left: Integer read FLeft write FLeft; property Top: Integer read FTop write FTop; end; TCustomGrid = class(Tobject) private FCols: Integer; FRows: Integer; FRowsContainer: TObjectList; procedure SetCols(AValue: Integer); procedure SetRows(AValue: Integer); public constructor Create; destructor Destroy; override; procedure Paint; property Cols: Integer read FCols write SetCols; property Rows: Integer read FRows write SetRows; end; var l, t, w, h: Integer; { TGridColumn } constructor TGridColumn.Create; begin inherited Create; end; { TCustomGrid } constructor TCustomGrid.Create; begin inherited Create; FRowsContainer := TObjectList.Create; end; destructor TCustomGrid.Destroy; begin FRowsContainer.Free; inherited; end; procedure TCustomGrid.SetCols(AValue: Integer); var ACol, ARow: Integer; gridColumn: TGridColumn; begin if FCols = AValue then Exit; FCols := AValue; for ARow := 0 to FRows - 1 do begin for ACol := 0 to FCols - 1 do begin gridColumn := TGridColumn.Create; gridColumn.Width := 200; gridColumn.Height := 20; gridColumn.Left := 10; gridColumn.Top := 10; TStringList(FRowsContainer.Items[ARow]).AddObject(' ', gridColumn); end; end; end; procedure TCustomGrid.SetRows(AValue: Integer); var ARow: Integer; AList: TStringList; begin if FRows = AValue then Exit; FRows := AValue; if FRowsContainer.Count > 0 then FRowsContainer.Clear; // falls mehrfacher Aufruf von SetRows Container löschen; for ARow := 0 to FRows - 1 do begin AList := TStringList.Create; AList.Capacity := 5; AList.Duplicates := dupAccept; FRowsContainer.Add(AList); end; end; procedure TCustomGrid.Paint; var ACol, ARow { , r, b } : Integer; gc: TGridColumn; sl: TStringList; rc: TObjectList; begin for ARow := 0 to FRowsContainer.Count - 1 do begin for ACol := 0 to TStringList(FRowsContainer.Items[ARow]).Count - 1 do begin rc := FRowsContainer; sl := TStringList(rc.Items[ARow]); gc := TGridColumn(sl.Objects[ACol]); if (ACol < TStringList(FRowsContainer.Items[ARow]).Capacity) and Assigned(TGridColumn(TStringList(FRowsContainer.Items[ARow]).Objects[ACol])) then begin // TGridColumn(TStringList(FRowsContainer.Items[ARow]).Objects[ACol]).Width; w := gc.Width; // TGridColumn(TStringList(FRowsContainer.Items[ARow]).Objects[ACol]).Height; h := gc.Height; // TGridColumn(TStringList(FRowsContainer.Items[ARow]).Objects[ACol]).Left; //aus Originalcode übernommen l := l + gc.Left; // TGridColumn(TStringList(FRowsContainer.Items[ARow]).Objects[ACol]).Top; //aber hier weggelassen t := t + gc.Top; end; writeln('Top: ', t); writeln('Left: ', l); inc(t, h); inc(l, w); end; end; end; var Grid: TCustomGrid; begin try { TODO -oUser -cConsole Main : Code hier einfügen } Grid := TCustomGrid.Create; Grid.Rows := 5; // zuerst Rows initialisieren dann Cols. Grid.Cols := 9; Grid.Paint; writeln('Zurück mit << ENTER >> > >>> ... '); readln; except on E: Exception do writeln(E.ClassName, ': ', E.Message); end; end. Zitat:
![]() Wie Uwe schon schrieb.. Zitat:
Und ignoriere keine Warnungen vom Compiler! w, h müssen ebenfalls global definiert werden weil diese ansonsten nicht initialisiert sind. Alternativ kannst du die auch local definieren mußt diese dann aber selbst initialisieren und zwar vor der schleife
Delphi-Quellcode:
for ARow := 0 to FRowsContainer.Count - 1 do
Delphi-Quellcode:
EDIT:
w := 0;
h := 0; Nebenbei das kann auch nicht stimmen.
Delphi-Quellcode:
DrawRectangleClip(vscreen,l,t,l+w,t+h,ToColor(colBlack));
Das
Delphi-Quellcode:
ist korrekt.
DrawRectangleClip(vscreen,l,t,w,h,ToColor(colBlack));
Hochladen tu ich hier nichts mehr da die kompilierte EXE wieder mal als ![]() Da die Administration so freundlich ist alle meine Projekte hier zu Untergraben spare ich mir das. |
AW: EListError, warum? ObjectList mit Daten füllen
[QUOTE=venice2;1506171]Ok du hast Rows und Cols vertauscht.. deshalb wurde deine TStringliste nicht gefüllt in deinem Beispiel!
Versuche das hier. Habe keinen ElistError läuft wie es soll.
Delphi-Quellcode:
Danke wie verrückt! Brett vorm Kopp gehabt, bei den vertauschten Dimensionen. Oh Mann, manchmal ist es einfach zum Verzweifeln, man findet den Fehler nicht und dann ist es so ne simple Sache. :wall: Vier Augen sehen oft mehr als nur zwei! Danke! Funktioniert nun wie es soll. :hello:
program Project3;
{$APPTYPE CONSOLE} {$R *.res} uses System.SysUtils, System.Classes, Contnrs; type TGridColumn = class(Tobject) private FWidth: Integer; FHeight: Integer; FLeft: Integer; FTop: Integer; public constructor Create; property Width: Integer read FWidth write FWidth; property Height: Integer read FHeight write FHeight; property Left: Integer read FLeft write FLeft; property Top: Integer read FTop write FTop; end; TCustomGrid = class(Tobject) private FCols: Integer; FRows: Integer; FRowsContainer: TObjectList; procedure SetCols(AValue: Integer); procedure SetRows(AValue: Integer); public constructor Create; destructor Destroy; override; procedure Paint; property Cols: Integer read FCols write SetCols; property Rows: Integer read FRows write SetRows; end; var l, t, w, h: Integer; { TGridColumn } constructor TGridColumn.Create; begin inherited Create; end; { TCustomGrid } constructor TCustomGrid.Create; begin inherited Create; FRowsContainer := TObjectList.Create; end; destructor TCustomGrid.Destroy; begin FRowsContainer.Free; inherited; end; procedure TCustomGrid.SetCols(AValue: Integer); var ACol, ARow: Integer; gridColumn: TGridColumn; begin if FCols = AValue then Exit; FCols := AValue; for ARow := 0 to FRows - 1 do begin for ACol := 0 to FCols - 1 do begin gridColumn := TGridColumn.Create; gridColumn.Width := 200; gridColumn.Height := 20; gridColumn.Left := 10; gridColumn.Top := 10; TStringList(FRowsContainer.Items[ARow]).AddObject(' ', gridColumn); end; end; end; procedure TCustomGrid.SetRows(AValue: Integer); var ARow: Integer; AList: TStringList; begin if FRows = AValue then Exit; FRows := AValue; if FRowsContainer.Count > 0 then FRowsContainer.Clear; // falls mehrfacher Aufruf von SetRows Container löschen; for ARow := 0 to FRows - 1 do begin AList := TStringList.Create; AList.Capacity := 5; AList.Duplicates := dupAccept; FRowsContainer.Add(AList); end; end; procedure TCustomGrid.Paint; var ACol, ARow { , r, b } : Integer; gc: TGridColumn; sl: TStringList; rc: TObjectList; begin for ARow := 0 to FRowsContainer.Count - 1 do begin for ACol := 0 to TStringList(FRowsContainer.Items[ARow]).Count - 1 do begin rc := FRowsContainer; sl := TStringList(rc.Items[ARow]); gc := TGridColumn(sl.Objects[ACol]); if (ACol < TStringList(FRowsContainer.Items[ARow]).Capacity) and Assigned(TGridColumn(TStringList(FRowsContainer.Items[ARow]).Objects[ACol])) then begin // TGridColumn(TStringList(FRowsContainer.Items[ARow]).Objects[ACol]).Width; w := gc.Width; // TGridColumn(TStringList(FRowsContainer.Items[ARow]).Objects[ACol]).Height; h := gc.Height; // TGridColumn(TStringList(FRowsContainer.Items[ARow]).Objects[ACol]).Left; //aus Originalcode übernommen l := l + gc.Left; // TGridColumn(TStringList(FRowsContainer.Items[ARow]).Objects[ACol]).Top; //aber hier weggelassen t := t + gc.Top; end; writeln('Top: ', t); writeln('Left: ', l); inc(t, h); inc(l, w); end; end; end; var Grid: TCustomGrid; begin try { TODO -oUser -cConsole Main : Code hier einfügen } Grid := TCustomGrid.Create; Grid.Rows := 5; // zuerst Rows initialisieren dann Cols. Grid.Cols := 9; Grid.Paint; writeln('Zurück mit << ENTER >> > >>> ... '); readln; except on E: Exception do writeln(E.ClassName, ': ', E.Message); end; end. Zitat:
|
AW: EListError, warum? ObjectList mit Daten füllen
Zitat:
Du weist(Initialisierst) einer variable den wert innerhalb einer Schleife zu. Der Compiler erkennt das aber nicht und gibt die Warnung aus das deine variable nicht initialisiert ist. w, h kann also einen imaginären wert enthalten. Definierte Variablen innerhalb deiner procedure, function können sich nicht selbst initialisieren das mußt du schon selber tun wenn der Compiler die Warnung ausgibt. Und zwar immer vor der entsprechenden Schleife innerhalb nutzt es nichts, wie schon gesagt der Compiler kennt den wert nicht. Deshalb sollte man Warnungen nicht einfach ignorieren. Mit t, l verhält es sich wie folgt. Diese Variablen in der procedure, function zu initialisieren macht keinen sinn weil du diese ja hochzählen willst "Außerhalb der Funktion" deshalb muß diese global oder zumindest innerhalb der Class definiert werden damit diese den Standard wert erhält in diesen Fall 0. Nur außerhalb deiner procedure, function können diese Hochgezählt werden damit die neuen Werte beim nächsten Aufruf erhalten bleiben. Innerhalb dieser wären sie wieder nicht initialisiert. Dein Aufruf!
Delphi-Quellcode:
ergibt also das Ergebnis l = 0 + 10 inkrementiert mit width l := 220 + 200 usw..
l := l + gc.Left;
Wäre l in deiner Procedure definiert könnte das Ergebnis so aussehen l = 12345 + 10 (weil deine Variable l nicht initialisiert bzw. global definiert wurde) Ein hochzählen der Variable l bringt nichts wenn diese nicht global definiert ist da diese innerhalb der Schleife immer wieder neu zugewiesen wird und somit immer den wert "Irgendeine Zahl + 10" erhält. Wenn dir irgendein Informatiker das hier besser erklären kann. Bitte schön! EDIT: Wenn du nicht möchtest das man von außen global auf die Variablen zugreifen kann dann addiere diese zu deiner TCustomGrid Class
Delphi-Quellcode:
TCustomGrid = class(Tobject)
private FCols: Integer; FRows: Integer; FRowsContainer: TObjectList; l, t, w, h: Integer; // hier! procedure SetCols(AValue: Integer); procedure SetRows(AValue: Integer); public constructor Create; destructor Destroy; override; procedure Paint; property Cols: Integer read FCols write SetCols; property Rows: Integer read FRows write SetRows; end; |
Alle Zeitangaben in WEZ +1. Es ist jetzt 11:10 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-2025 by Thomas Breitkreuz