![]() |
Alle Controls mit FOR-IN durchlaufen?
Hai,
ist es möglich diesen Code:
Delphi-Quellcode:
mit dieser "FOR-IN" Konstruktion zu ersetzen?
var
ndx : Integer; begin for ndx := 0 to Panel1.ControlCount -1 do begin if (Panel1.Controls[ndx] is TSpeedButton) then begin (Panel1.Controls[ndx] as TSpeedButton).Glyph := nil; end; end; end; Irgendwie blicke ich bei der noch nicht so richtig durch. :gruebel: |
Re: Alle Controls mit FOR-IN durchlaufen?
Hi,
bei der Controls Eigenschaft von TForm gibt es keine Möglichkeit diese mit einer for..in Schleife zu durchlaufen, da es sich um eine Array-Property handelt. (Controls.pas, Z. 1462). Aber, vielleicht geht es ja so:
Delphi-Quellcode:
mfG
var
Control: TComponent; begin for Control in Self do if Control is TSpeedButton then TSpeedButton(Control).Glyph := nil; mirage228 |
Re: Alle Controls mit FOR-IN durchlaufen?
Hai mirage228,
Danke für deine Antwort. Leider werden in diesem Fall alle Componenten von Form1 durchlaufen. Mir ging es aber in diesem Fall nur um die TSpeedButton die auf Panel1 liegen. Jetzt kann ich das natürlich mit einer weiteren IF-Abfrage prüfen. Nur ist dann der "Vorteil" des FOR-IN wieder dahin. |
Re: Alle Controls mit FOR-IN durchlaufen?
Hi,
oh, da hatte ich mich wohl verlesen. Was mit TForm geht, sollte natürlich auch mit TPanel klappen:
Delphi-Quellcode:
mfG
var
Control: TComponent; begin for Control in Panel1 do if Control is TSpeedButton then TSpeedButton(Control).Glyph := nil; end; mirage228 |
Re: Alle Controls mit FOR-IN durchlaufen?
Zitat:
Ich fürchte es liegt daran das der Owner der Buttons die Form und nicht das Panel ist. |
Re: Alle Controls mit FOR-IN durchlaufen?
Hi,
habs mal getestet: Der Owner der Speedbuttons ist tatsächlich das Form, und nicht das Panel. :? Da fällt mir nur dieser Code zu ein:
Delphi-Quellcode:
mfG
var
Control: TComponent; begin for Control in Self do if (Control is TSpeedButton) and (TSpeedButton(Control).Parent = Panel1) then TSpeedButton(Control).Glyph := nil; mirage228 |
Re: Alle Controls mit FOR-IN durchlaufen?
Hallo Sharky,
Zitat:
Code:
Grüße vom marabu
var
Control: TComponent; begin for Control in Panel1 do // muss heißen: Panel1.Controls if Control is TSpeedButton then TSpeedButton(Control).Glyph := nil; end; |
Re: Alle Controls mit FOR-IN durchlaufen?
Hi marabu,
genau .Controls geht ja nicht. Den Grund habe ich schon in meinem ersten Posting geschrieben... Der Enumerator von TComponent bezieht sich nur auf das Components und nicht auf das Controls Array. mfG mirage228 |
Re: Alle Controls mit FOR-IN durchlaufen?
Dann bleibe ich in diesem Fall bei meinem ersten Code. Da dieser nur die Controls auf dem Panel durchläuft ist er effektiver als die FOR-IN Variante.
|
Re: Alle Controls mit FOR-IN durchlaufen?
Lasst mich nicht dumm sterben. Ich arbeite noch mit D7. Warum kann das FOR-IN-Konstrukt für Components verwendet werden, aber nicht für Controls? Warum nicht für Arrays? Waldteufel hat mir eben in der Online-Hilfe von D2005 gezeigt, dass FOR-IN mit ArrayExpr, StringExpr, SetExpr und CollectionExpr funktionieren soll. Warum also nicht mit einem Controls-Array? Ist da ein Fehler in der Dokumentation?
marabu |
Re: Alle Controls mit FOR-IN durchlaufen?
Hallo marabu,
der Grund ist wahrscheinlich der fehlende Enumerator. sakura hat mal ein gutes Beispiel gepostet, wie man diese Funktionalitaet nachtraeglich noch einbauen kann: ![]() In Delphi 7 gibt es das for-in-do-Konstrukt leider nicht, also wirst du dort immer noch auf die "alte" Variante mit Laufvariablen zurueckgreifen muessen, ausser du baust dir irgendwie einen Enumerator rein, und machst manuell das, was der Delphi-Compiler fuer dich reinschreibt:
Delphi-Quellcode:
Am Ende ist es das, was der Compiler aus deiner for-in-do-Schleife macht. Der einzige Unterschied ist hier die Verwendung von GetIEnumerator anstatt GetEnumerator in Delphi 2005. Warum das so ist, weiss ich im Moment auch nicht :oops:
with SomeCollection.GetIEnumerator() do
begin while MoveNext() do begin Current.SomeProperty := SomeValue; end; end; Greetz alcaeus |
Re: Alle Controls mit FOR-IN durchlaufen?
Hallo alcaeus,
danke für deinen Hinweis. Habe nochmal etwas genauer in die Online-Hilfe geschaut. Nach meinem jetzigen Kenntnisstand ist da ein Unterschied zwischen methoden-gestützter Iteration und dem Sprachmittel FOR-IN, denn laut OH D2005 ist folgendes möglich:
Delphi-Quellcode:
Da ist doch bestimmt kein Enumerator im Spiel, oder? Das müsste der Compiler doch einfach so schaffen! Und dass der Compiler Panel1.Controls nicht als ArrayAusdruck akzeptiert, liegt wohl wirklich daran, dass es sich um eine Array Property handelt - worauf mirage228 schon eingangs hinwies. Da der Zugriff über eine Funktion mit dem Parameter index geschieht, kann sich alles und nichts hinter dieser array property verbergen, z.B. auch sowas:
var
i: integer; ai: array of integer; begin sum := 0; for i in ai do Inc(sum, i); end;
Delphi-Quellcode:
Danke an alle die zu meiner Erleuchtung beigetragen haben.
function GetArrayItem(index: integer): integer;
begin if index < 2 then Result := index else Result := GetArrayItem(Pred(index)) + index; end; Grüße vom marabu |
Re: Alle Controls mit FOR-IN durchlaufen?
Zitat:
TComponent implementiert die Methode "GetEnumerator", welche für das FOR..IN benötigt wird, nur für die Components Eigenschaft (welche im Übrigen kein Array, sondern eine Liste (TList) ist). Die .Controls Eigenschaft kann nicht mit for..in durchlaufen werden, da es sich nicht um ein Array im eigentlichen Sinne handelt, sondern um eine Array-Eigenschaft ("array property"). Mit "normalen" Arrays, sowie auch mit TList selbst, funktioniert FOR..IN wie gewünscht. mfG mirage228 Edit: Schon wieder kein roter Kasten :-( |
Re: Alle Controls mit FOR-IN durchlaufen?
Hallo David,
danke nochmal - ich denke ich habe das jetzt soweit durchdrungen, wie ich es mit D7 durchdringen muss. Vielleicht installiere ich irgendwann auch mal die D2005 PE. marabu |
Re: Alle Controls mit FOR-IN durchlaufen?
Liste der Anhänge anzeigen (Anzahl: 1)
Irgendwas geht hier nicht mit rechten Dingen zu...
Um "for in" anwenden zu können, brauche ich eine Instanz einer Klasse, die eine funktion GetEnumerator besitzt, welche eine Instanz einer Klasse liefert, die MoveNext, Current und GetCurrent besitzt. Richtig bisher, oder? Die Wurzel allen Übels wäre wohl diese Klassen:
Delphi-Quellcode:
Der Enum ist abstrakt, da ich in der Unit alle Klassen habe, die nach außen hin benötigt werden.
type
TControlEnumerator = class protected function getOwner: TWinControl;virtual;abstract; function getPosition: Integer;virtual;abstract; property Owner :TWinControl read getOwner; property Position :Integer read getPosition; public function getCurrent :TControl; virtual;abstract; function MoveNext :Boolean; virtual;abstract; property Current :TControl read getCurrent; end; IControlIterator = interface function getOwner :TWinControl; function GetEnumerator :TControlEnumerator; property Owner :TWinControl read getOwner; end; TControlIterator = class(TInterfacedObject) public class function GetInstance(aOwner :TWinControl) :IControlIterator;overload; class function GetInstance(aOwner :TWinControl; aControlClass :TControlClass) :IControlIterator; overload; end; Deshalb sollte hier IMHO keinerlei Funktionalität reinquetscht werden. (bis auf die Factories...) Das hier funktioniert sowohl in D7 als auch in D2005:
Delphi-Quellcode:
Das hier kompiliert zwar in D2005...
with TControlIterator.GetInstance(self, TButton).GetEnumerator do
while MoveNext do ListBox1.Items.Add(Current.Name);
Delphi-Quellcode:
...aber er springt zur deklaration von MoveNext in TControlEnumerator und sagt mir "abstract error..." :evil:
for Control in TControlIterator.GetInstance(self, TButton) do
ListBox1.Items.Add(Control.Name); Haben wir heute den ersten April und ich hab's verpasst? :shock: Wer mal in den angehängten Code schaut dürfte sofort sehen, dass ich eine Instanz des Enums zurückgebe, deren Klasse MoveNext überschreibt... :evil: Ich habe jetzt eine Weile rumgedoktort, aber egal was man versucht: D2005 scheint sich stupide und fix auf die Methoden der Klasse zu stürzen, die GetEnumerator liefert. Ohne auch nur daran zu denken, dass sie überschrieben sein könnten. Sorry Sharky, ich hab's versucht, aber das ist mir auf Dauer einfach zu doof... :? Wie gesagt, ich habe den Code angehängt. Wer was draus machen will: be my guest... |
Re: Alle Controls mit FOR-IN durchlaufen?
Zitat:
So wie ich es sehe werde ich auf FOR-IN grundsätzlich verzichten. Wenn ich erst versuchen muss ob es für den gerade notwendigen Zweck einen Enumerator gibt ist das alles nichts anderes als ein weiterer Marketing-Gack :wall: |
Alle Zeitangaben in WEZ +1. Es ist jetzt 14: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