![]() |
TCollection, TCollectionItem
Liste der Anhänge anzeigen (Anzahl: 1)
Hallo,
ich habe am Anfang des Jahres angefangen meine erste Komponente zu programmieren, da ich jetzt wieder mehr Zeit habe möchte ich gerne daran weiterarbeiten. Es soll eine Kalenderkomponente werden abgeleitet von TCustomGrid. Auf diesem Grid soll man Objekte abgeleitet von TGraphicControl ablegen können, die die Einträge im Kalender verwalten. Siehe Screenshot. Um diese Objekte zu verwalten müßte ich meiner Komponente nun die Klasse TCollection hinzufügen, glaube ich jedenfalls. So und nun zu meinem Verständnisproblem: 1. Wo muß ich die Klasse TCollection erstellen, wahrscheinlich beim erstellen meines Grids, oder? 2. Müssen die TCollectionItems von meinen Einträgen oder die Einträge von TCollectionItems erstellt werden? Falls jemand etwas direkt in meinen Source schreiben will, kann ich ihn auch noch anhängen. Habe mir schon sehr viele Quellcodes angeschaut, da aber in den meisten alle möglichen Klassen verschachtelt sind habe ich die Logik einfach noch nicht verstanden. Hoffe es wahr einigermaßen verständlich was ich von Euch möchte. Danke im voraus Uwe |
Re: TCollection, TCollectionItem
Hi,
Ok, vielleicht war meine Frage zu kompliziert gestellt, deshalb versuche ich es nocheinmal. Ich habe mir ein Grid erstellt, in dem ich das Datum in Spalten und die Uhrzeit oder frei definierbare Texte, in Zeilen anzeigen lassen kann. Auf dieses Grid, möchte ich DateItems als Einträge im Kalender anzeigen lassen. Siehe Screenshot erstes Posting.
Delphi-Quellcode:
Wie kann ich am besten die Einträge(TDateItem) verwalten, in TCollection? Oder gibt es bessere Methoden?
TDateLine = TCustomGrid
TDateItem = TGraphicControl Wie müßte ich das ganze dann aufbauen, wo was deklarieren. Für die Zukunft würde ich gerne auch die Einträge in einer DB speichern können. Hoffe es gibt doch jemand da draußen, der mir eine kleine Hilfestellung geben kann. Danke |
Re: TCollection, TCollectionItem
Hi,
grundsätzlich halte ich TCollection für den richtigen Weg. Nun progge ich nicht jeden Tag Kompos mit TCollection und kann somit meine Hand nicht dafür ins Feuer legen, dass das der perfekte Weg ist. Aber so habe ich es gemacht. Günstig ist es auf jeden Fall ein TListItem-element als Hilfe wie es funst zu benutzen. als erstes benötigst du ein Control, welches deine Elemente hält. Das hast du ja schon; deine Kalenderkompo als TCustomGrid. Diese benötigt jetzt eine property Items. das sieht dann etwa so aus:
Delphi-Quellcode:
Mein TCollection-Object sieht dann so aus
TMyControl = class(TCustomControl)
private procedure SetMyItems(const Value: TLCItems); published property Items: TMyItems read FMyItems write SetMyItems; end; procedure TLineControl.SetMyItems(const Value: TMyItems); begin FMyItems.Assign(Value); end;
Delphi-Quellcode:
Hier sind zwei Sachen entscheidend, im Constructor wird das Parent-Control aufgerufen. Dies erfolgt, um denren Zeichenroutinen nach Änderung der Item aufrufen zu können. Im weiteren händelt die Collektion die grundlegenden Methoden für die Erstellung und den Zugriff auf die Item.
TMyItems = class(TCollection)
private FLineControl: TMyControl; function GetItem(Index: Integer): TMyItem; procedure SetItem(Index: Integer; Value: TMyItem); protected function GetOwner: TPersistent; override; procedure Update(Item: TCollectionItem); override; public constructor Create(AControl: TMyControl); function Add: TMyItem; procedure Refresh; property Items[Index: Integer]: TMyItem read GetItem write SetItem; default; end; // hier ein Bspiel für SetItem procedure TMyItems.SetItem(Index: Integer; Value: TMyItem); begin inherited SetItem(Index, Value); end; Die Item sehen dann so aus:
Delphi-Quellcode:
Denk an die Forward-Deklaration für TMyItems und TMyControl.
TMyItem = class(TCollectionItem)
private FParent: TLCItems; FRect : TRect; FCaption: String; procedure SetCaption(const Value: String); protected public constructor Create(Collection: TCollection); override; procedure Update; virtual; procedure Assign(Source: TPersistent); override; property Data : Pointer read FData write FData; published property Caption : String read FCaption write SetCaption; end; gezeichnet wird im TMyControl. Dazu besitzt bei mir TMyControl eine Methode
Delphi-Quellcode:
Hierbei ist Canvas der Canvas von TMyControl. Es wird direkt in den Canvas gezeichnet. Ob das so die ideale Methode ist mag ich nicht zu sagen. Vielleicht hast du oder ein anderer eine bessere Idee.
procedure DrawItem(Item: TLCItem; ACanvas: TCanvas; var R: TRect); virtual;
gruß oki |
Re: TCollection, TCollectionItem
Erstmal Vielen Dank oki,
werde mir das ganze mal durch den Kopf gehen lassen und natürlich auch ausprobieren. Danke, Danke! |
Re: TCollection, TCollectionItem
Hi uwewo,
habe deinen code bekommen und schon mal rein geschaut. Ich glaube hier muß man eine grundsätzliche Entscheidung für die Vorgehensweise finden. entweder man benutzt TCollections oder eigene Listen in denen die Elemente gehalten werden. Hierbei ist es dann aber so, dass bei TCollection der weg an TColletionItem nicht vorbei geht. Hier ist dann nichts mit TCustomControl!!! Ein Trick ist es dann vielleicht, wenn mann das CustomControl (hier TDateItem) in einer neuen Eigenschaft "Controldata" versteckt. Ob der Aufwand damit aber nicht zu hoch wird ist hier die Frage. Alternativ könnte man dann über Object-Listen arbeiten, in denen dann die DateItem gesammelt werden. Ob das weniger Aufwand ist? Keine Ahnung. Egal über welchen Weg du gehst, helfen kann ich dir sicher. Das es der effektivste Weg ist kann ich aber nicht garantieren. Die Thematik eines anständigen Item-Editors zu designtime hab ich persönlich jedoch noch nicht umgesetzt (war mir für eigene Kompos zu viel Aufwand). o.k. sag welche Methode du möchtest und es kann los gehen. Gruß oki P.S. Nach dem ich meinen eigenen Beitrag noch mal gelesen habe tendiere ich zu den TCollection. |
Re: TCollection, TCollectionItem
Hallo oki,
danke das Du es dir angeschaut hast, TCollection denke ich wird der richtige Weg sein. Wäre es möglich TCollection und TCollectionItem zu erstellen, und nur die Eigenschaften von TDateItem in TCollectionItem zu lesen und zu schreiben? Damit die eigentliche Routine zum zeichnen, sowie die Eigenschaften von TDateItem in der Klasse TDateItem bleiben? |
Re: TCollection, TCollectionItem
Hi,
Zitat:
Das ist wohl so üblich. Die nächste Frage ist jetzt aber ob man nicht auch einen anderen Weg gehen kann. Wenn es sinn macht die Einträge als TWincontrol auf dem Parent darzustellen, dann kann man natürlich dem TCollectionItem auch eine Eigenschaft vom Typ TControlItem(TCustomControl) verpassen. Deises dann auf das Parent geklebt, und mann spart sich die vielen aufwendigen Zeichenroutinen. Bedenke, das geder Eintrag gezeichnet werden muß, und das für mehrere Zustände (selektiert, nicht selektiert etc.) Ich glaube das grundlegende Plroblem wird wohl eher die Performance sein. Nun gut, zur not können wir es ja einfach ausprobieren. Ich hab mal angefangen deinen Code zu überarbeiten und werde ihn sicher heute Versandfertig haben. Dann können wir die ersten Sachen vielleicht heute testen und die ersten Ergebnisse posten. Gruß oki |
Re: TCollection, TCollectionItem
Hört sich ja gut an. Wenn ich schon etwas vorbereiten kann das Dir hilft, sag Bescheid.
Das Zeichnen der Items auf dem Grid funktioniert ja soweit schon, ich weiß natürlich nicht ob Du es ausprobiert hast. |
Re: TCollection, TCollectionItem
Hi,
tschuldige, aber ich bin in 1 Minute offline. Nein hab ich nicht getestet, mach ich noch. Bin nur gerade beim umschreiben. bis später Gruß oki |
Re: TCollection, TCollectionItem
Hi uwewo,
so, jetzt mal zum Ansatz und Aufbau deiner neuen Kompo TDateLine. TDateLine ist vom Typ TCustomGrid und damit ein Nachfahre von TComponent. TDateLine hält einen Member TDateItems vom Typ TCollection. TDateItems hält die Einträge TDateItem vom Typ TCollectionItem. Da du deine Einträge gerne als TCustomControls haben möchtest, hält jetzt genau jedes TDateItem ein TControlDateItem vom Typ TCustomControl. Somit verknüpfen wir ursächlich jedes Control mit einem Listeneintrag im DateLine. das sieht im Objectaufbau etwa so aus:
Delphi-Quellcode:
Ich habe hier die spezifischen Eigenschaften weg gelassen.
// Forward
TDateLine = class; TDateItems = class; TControlDateItem = class(TCustomControl) private { Private-Deklarationen } protected { Protected-Deklarationen } procedure Paint; override; public { Public-Deklarationen } constructor Create(AOwner: TComponent); override; destructor Destroy; override; published { Published-Deklarationen } end; TDateItem = class(TCollectionItem) private FParent : TDateItems; FControlDateItem : TControlDateItem; protected public constructor Create(Collection: TCollection); override; end; TDateItems = class(TCollection) private FDateLine: TDateLine; function GetItem(Index: Integer): TDateItem; procedure SetItem(Index: Integer; Value: TDateItem); protected function GetOwner: TPersistent; override; procedure Update(Item: TDateItem); reintroduce; public constructor Create(DateLine: TDateLine); function Add: TDateItem; procedure Refresh; property Items[Index: Integer]: TDateItem read GetItem write SetItem; default; end; TDateLine = class(TCustomGrid) private { Private-Deklarationen } FDateItems : TDateItems; protected { Protected-Deklarationen } public { Public-Deklarationen } constructor Create(AOwner: TComponent); override; destructor Destroy; override; property Items: TDateItems read FDateItems write SetDateItems; end; Ein neues Item im DateLine kann jetzt wie gewohn erschaffen werden.
Delphi-Quellcode:
Im Constructor von TDateItem geschieht jetzt folgendes:
var Item : TDateItem;
begin Item := MyLineControl.Items.Add;
Delphi-Quellcode:
Es wird automatisch ein zugehöriges TControlDateItem kreiert. Achte aber darauf, dass der Owner hier nicht self (das Item) sonder TDateLine, also die Kompo ist. Dort soll das Control ja auch platziert werden.
constructor TDateItem.Create(Collection: TCollection);
begin inherited Create(Collection); FParent := TDateItems(Collection); FControlDateItem := TControlDateItem.Create((Collection as TDateItems).FDateLine); end; Jetzt ist mir aufgefallen, dass du ne menge obstruser Eigenschaften definierst. Bsp.
Delphi-Quellcode:
Ich unterstell mal, das bei entsprechenden Kalendereinträgen niemand die Breite und Höhe in Pixeln eingibt. Damit sind diese Werte für diese Anwendung wenn schon nicht im Public, so doch im published-Teil sehr fraglich.
TControlDateItem = class(TCustomControl)
private { Private-Deklarationen } protected { Protected-Deklarationen } public { Public-Deklarationen } published { Published-Deklarationen } property Height;// default 65; property Width;// default 65; property ColLeft : Integer read FColLeft write FColLeft; property RowTop : Integer read FRowTop write FRowTop; property ColCount : Integer read FColCount write FColCount; property RowCount : Integer read FRowCount write FRowCount; property Shape : TItemForm read FShape write SetShape; property Brush : TBrush read FBrush write SetBrush; property Pen : TPen read FPen write SetPen; property Text : String read FText write SetText; property Font : TFont read FFont write SetFont; end; Hie veröffentlicht mann eher die Eigenschaften:
Delphi-Quellcode:
die entsprechenden Set-Methoden berechnen und setzen dann die richtigen Werte für Höhe, Breite und Position im DateLine. Bei einer Aktualisierung brauchen dann auch nur noch diese Methoden aufgerufen werden und das Control passt sich automatisch den neuen Einstellungen von DateLine an.
property StartDate : TDateTime read FStartDate write SetStartDate;
property EndDate : TDateTime read FEndDate write SetEndDate; Bu, jetzt hab ich krumme Finger, bis später oki P.S. in meinem Code per PM entferne die Auskommentierungen vom 11.10 in TDateItems! |
Alle Zeitangaben in WEZ +1. Es ist jetzt 02:44 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