Delphi-PRAXiS
Seite 1 von 2  1 2      

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Object-Pascal / Delphi-Language (https://www.delphipraxis.net/32-object-pascal-delphi-language/)
-   -   Delphi Gleiche Variablen-Namen (https://www.delphipraxis.net/192650-gleiche-variablen-namen.html)

Delbor 8. Mai 2017 16:19

Delphi-Version: XE8

Gleiche Variablen-Namen
 
Hi zusammen

Zu Beginn: die bewusste Variable ist ein Feld vom Tip TStringlist und hat überall den selben Namen: FPathlist. Da (und solange) es sich dabei um ein privates Feld handelt, ist das im Grunde kein Problem.
Hier feuere ich einen Event und übergebe dabei unter anderem FPathlist:
Delphi-Quellcode:
procedure TPathFinderFrame.FileSearcher1ExecuteComplete(Sender: TObject);
  var LPathlist: TStringlist; LOrdner: String;
begin
  if Assigned(FCurrentNode) then
    FCurrentNode.Expand(false);
  if Assigned(FOnPathListEvent) then
  begin
//    LPathList := TStringlist.Create;
//    LPathList.AddStrings(LPathlist);
//    LOrdner := FOrdner;
    FOnPathListEvent(Sender, FOrdner, FPathlist);
  end;
end;
Die auskommentierten Zeilen zeigen schon meinen Lösungsansatz, indem ich vor dem Abfeuern lokale Variaben einführe. Das Problem zeigt sich beim Empfänger der FPathlist(wenn es denn wirklich eins ist):
Delphi-Quellcode:
procedure TSQLiteTestMain.DoPathListEvent(Sender: TObject;
  const FOrdner: String; const FPathlist: TStringList);
begin
  Self.EdiFolder.Clear;
  Self.EdiFolder.Text := FOrdner;
  Self.LBxPathlist.Clear;
  Self.LBxPathlist.Items.AddStrings(FPathlist);
end;
Wie der Klassenname der Form schon sagt, handelt es sich hier um eine Testanwendung. Wobei noch sehr simpel ist, was hier geschieht - die übergebenen Werte werden einfach ausgegeben.
Weniger simpel ist (oder scheint mir), was eigentlich geschehen soll: Der Übergabeparameter FPathlist soll an ein privates Feld FPathlist der Form TSQLiteTestMain übergeben werden, also FPathlist wird an FPathlist übergeben. Mich würde erstaunen, wenn dies keine Probleme macht, auch wenn das eine eine Konstante ist, das andere nicht.
Im Gegensatz von Funktionsparametern müssen Eventparameter offenbar nicht nur an der selben Position stehen, sondern auch gleich heissen.
Meine Frage ist also:
Gibt oder kann es Probleme geben, wenn ein Eventparameter an ein gleichnamiges Feld übergeben wird, wie ich vermute?

Gruss
Delbor

Uwe Raabe 8. Mai 2017 16:29

AW: Gleiche Variablen-Namen
 
Probleme gibt es wohl mit der Ownership - sprich, wer gibt die Instanz frei.

Aber warum genau willst du denn den FPathList-Parameter an das lokale Feld übergeben? Was willst du damit bewirken?

SneakyBagels 8. Mai 2017 16:33

AW: Gleiche Variablen-Namen
 
Ich mache das in etwa so

Pseudocode
Delphi-Quellcode:
prozedur1
var
 Variableninstanz Typ
begin
 Variableninstanz erstellen
 prozedur2(variableninstanz)
end

prozedur2 (variableninstanz: Typ = nil)
var
 gebeinstanzfrei Boolean
begin
 gebeinstanzfrei := False
 if variableninstanz = nil
  begin
   variableninstanz erstellen
   gebeinstanzfrei := True
  end

  .....

  if gebeinstanzfrei then
   variableninstanz.Free
end
Auf diese Art und Weise schicke ich eine bei Programmstart erstellte Variableninstanz von Ini bis an die Stelle an der das Programm komplett geladen ist.
Verwendet wird diese Instanz von einer Hand voll Prozeduren. Eine globale Instanz kommt nicht in Frage, das immer immer neu-erstellen in jeder Prozedur ebenfalls nicht.

Delbor 8. Mai 2017 16:49

AW: Gleiche Variablen-Namen
 
Hi Uwe Raabe
Zitat:

Aber warum genau willst du denn den FPathList-Parameter an das lokale Feld übergeben? Was willst du damit bewirken?
Ich habe mir einen eigenen FileOpenframe (TPathFinderFrame) geschrieben, und der füllt FPathList jeweils mit Dateipfaden, wenn ein Ordner geöffnet wird.
Verarbeitet wird diese Liste allerdings ausserhalb: aus den enthaltenen Pfaden sollen Bilddateien geladen werden und anschliessend in eine SQLite-DB geschrieben werden.

Zitat:

Probleme gibt es wohl mit der Ownership - sprich, wer gibt die Instanz frei.
Die FPathlist-Felder werden jeweils im Frame und in der Mainform erzeugt und auch da zerstört.

Gruss
Delbor

hoika 8. Mai 2017 18:23

AW: Gleiche Variablen-Namen
 
Hallo,
Zitat:

die FPathlist-Felder werden jeweils im Frame und in der Mainform erzeugt und auch da zerstört.
Warum nicht nur im Frame?

Delbor 8. Mai 2017 18:25

AW: Gleiche Variablen-Namen
 
Hi SneakyBagels

Tönt nicht schlecht - auf diese Weise hätte ich genau eine Instanz meiner FPathlist. Allerdings hat das in meinem Fall einen kleinen Haken:
FPathlist übernimmt in meinem PathfinderFrame die von DeddyH'sTFileSearch gefundenen Pfade:
Delphi-Quellcode:
procedure TPathFinderFrame.AddNewNode(ParentNode: TTreeNode; const aCaption,
  aRealName: string; CanGetChildren: Boolean);
var
  Node: TTreeNode;
  NameRec: PNameRec;
begin
  Node := TVPathExplorer.Items.AddChild(ParentNode, aCaption);
  if CanGetChildren then
    begin
      Node.ImageIndex := 1;
      Node.SelectedIndex := 1;
      (* Dummy-Knoten anlegen *)
      TVPathExplorer.Items.AddChild(Node, 'dummy');
    end
  else
    begin
      Node.ImageIndex := 2;
      Node.SelectedIndex := 2;
      FPathlist.Add(aRealName); //<==
    end;
  New(NameRec);
  NameRec^.RealName := aRealName;
  Node.Data := NameRec;
end;
AddNewNode wird das erste mal aus TPathFinderFrame.Create aus aufgerufen, um die Ordner der ersten Ebene darzustellen (Laufwerke). Danach erfolgen die Aufrufe immer aus den Expanding-Events des Treeviews. Denen kann ich die Liste nicht per Aufruf übergeben, da diese per Mousedown ausgelöst werden (wenn der User einen Ordner anklickt). Und bei jedem Klick eine neue Instanz erstellen, dürfte auch nicht wirklich das Wahre sein.

Gruss
Delbor

SneakyBagels 8. Mai 2017 18:37

AW: Gleiche Variablen-Namen
 
Danke für das Lob. Hätte eigentlich gedacht du erschlägst mich wegen dieser zusammengebastelten Lösung welche alles andere ist als OOP.

Delbor 8. Mai 2017 18:55

AW: Gleiche Variablen-Namen
 
Hi Hoika

Zitat:

Zitat:
die FPathlist-Felder werden jeweils im Frame und in der Mainform erzeugt und auch da zerstört.
Zitat:

Warum nicht nur im Frame?
Weil ich dann jeweils von der Mainform aus mit der Framepathlist arbeiten müsste. Da FPathlist ein privates Feld ist, ist dies nicht möglich, ausser ich mache das Feld zu einer Public-Variable.
Klar, ich könnte so aus jeder Unit mit der Framevariable arbeiten. Aber sobald sich in einem Projekt keine PathfinderFrame befindet, muss ich in allen Units, die darauf zugreifen, dies unterbinden - das heisst, ich müsste alle diese Units bearbeiten.

Nach dem Schichtenmodell kann zwar die GUI auf die Logikschicht, zum Beispiel ein Datenmoudul, zugreifen, aber nicht umgekehrt. Das erspart bei Änderungen eine Menge arbeit.

Gruss
Delbor

DeddyH 8. Mai 2017 19:08

AW: Gleiche Variablen-Namen
 
Wenn der FileSearcher und am besten auch die ihm zugewiesenen EventHandler zum Frame gehören, würde ich die Stringliste auch als privates Feld (und ggf. Public ReadOnly-Property) des Frames deklarieren, dann ist alles schön beisammen und man kommt nicht durcheinander.

Delbor 8. Mai 2017 19:27

AW: Gleiche Variablen-Namen
 
Hi SneakyBagels
Zitat:

...wegen dieser zusammengebastelten Lösung welche alles andere ist als OOP.
Grundsätzlich sind lokale Variablen, die mit Prozedur- oder Funktionsaufrufen übergeben werden, absolut OOP-Konform.
Allerdings habe ich deinen Beitrag nicht wirklich ganz verstanden.


Zitat:

Auf diese Art und Weise schicke ich eine bei Programmstart erstellte Variableninstanz von Ini bis an die Stelle an der das Programm komplett geladen ist.
Das heisst also, du deklarierst und erzeugst die Variable in der ProjektUnit noch bevor Mainform.Create aufgerufen wird? Das ist tatsächlich eher ungewöhnlich, aber meines Wissens noch kein Non-OOP.
Zitat:

Verwendet wird diese Instanz von einer Hand voll Prozeduren. Eine globale Instanz kommt nicht in Frage, das immer immer neu-erstellen in jeder Prozedur ebenfalls nicht.
Das habe ich nicht ganz verstanden. Ich verstand das erstmal so, dass du da einen äüsserst gut ausgeklügeltes Aufruf- und Übergabeschema benötigst und allenfalls die Instanz an Prozeduren übergibst, die damit nichts anderes machen, als sie selbst weiterzugeben. Aber auch das ist nicht Non-OOP.
Das Erstellen (und zerstören!) von lokalen Instanzen in einer Prozedur wird in vielen Beispielen angewendet und macht durchaus Sinn, ist aber nicht in jedem Fall Zielführend.

Gruss
Delbor

Delbor 8. Mai 2017 19:51

AW: Gleiche Variablen-Namen
 
Hi DeddyH
Zitat:

Wenn der FileSearcher und am besten auch die ihm zugewiesenen EventHandler zum Frame gehören, würde ich die Stringliste auch als privates Feld (und ggf. Public ReadOnly-Property) des Frames deklarieren, dann ist alles schön beisammen und man kommt nicht durcheinander.
Die Sache mit dem Property habe ich mir auch überlegt. Einen Event müsste ich vom Frame aus aber so oder so abfeuern, da die Mainform ja nicht wissen kann, wann der PathfinderFrame die Liste (und damit das Listenproperty) neu bestückt. Das würde dann heissen, dass ich vom Frame aus einen TNotifierEvent abfeuere, den die Mainform empfängt und dabei dann das Listen-Property des Frames ausliest.
So, wie ich Uwe Raabe aber verstanden habe, kann ich den FPathlist-Parameter des Frames problemlos an das private Feld FPathlist der Mainform zuweisen.
Ein vorgehen, dass mich auch in späteren Zeiten beim lesen meines Codes wohl immer etwas irritieren wird. Von daher wäre die Lösung mit dem Property wohl etwas klarer.

Gruss
Delbor

DeddyH 8. Mai 2017 19:56

AW: Gleiche Variablen-Namen
 
Also gibt es auch im Mainform eine entsprechende Liste? Dann ist eine 2. Instanz vermutlich Quatsch, da Du mit einer Public (jetzt aber nicht mehr ReadOnly) Property dasselbe erreichen kannst. Ich tippe hier am Tablet, sonst hätte ich mal schnell etwas Beispielcode geschrieben, so ist mir das aber zu mühsam.

hoika 8. Mai 2017 19:57

AW: Gleiche Variablen-Namen
 
Hallo,
Zitat:

Weil ich dann jeweils von der Mainform aus mit der Framepathlist arbeiten müsste. Da FPathlist ein privates Feld ist, ist dies nicht möglich, ausser ich mache das Feld zu einer Public-Variable.
Klar, ich könnte so aus jeder Unit mit der Framevariable arbeiten. Aber sobald sich in einem Projekt keine PathfinderFrame befindet, muss ich in allen Units, die darauf zugreifen, dies unterbinden - das heisst, ich müsste alle diese Units bearbeiten.
Dann nimm eine Globals-Unit, pack dort Deine Variablen rein (von mir aus auch als class var,
dann bleiben wir beim OOP)
die sowohl Main als auch der Frame benutzt.

Ansonsten ist das hier mit Kanonen auf Spatzen schießen.

Zitat:

dass ich vom Frame aus einen TNotifierEvent abfeuere
Und schon sind wir beim Event-Listener

DeddyH 8. Mai 2017 20:15

AW: Gleiche Variablen-Namen
 
Das ist aber doch keine Raketentechnik.
Delphi-Quellcode:
type
  TDingensFrame = class(TFrame)
  private
    FPathList: TStrings;
    ...
  public
    property PathList: TStrings read FPathList write FPathList;

...

procedure TDingensFrame.SomeEvent(Param: string);
begin
  if Assigned(FPathList) then
    FPathList.Add(Param);
end;
Jetzt kann das Formular der Frame-Property eine TStrings-Instanz zuweisen, und der nutzt dann diese. Damit gibt es nur eine Instanz, aber beide haben Zugriff darauf.

Uwe Raabe 8. Mai 2017 21:01

AW: Gleiche Variablen-Namen
 
Zitat:

Zitat von Delbor (Beitrag 1370617)
So, wie ich Uwe Raabe aber verstanden habe, kann ich den FPathlist-Parameter des Frames problemlos an das private Feld FPathlist der Mainform zuweisen.

Das habe ich so nicht gesagt! Es muss dann schon geklärt werden, wer da dann was frei gibt.

Besser wäre es, du würdest immer nur die Inhalte von einer StringList in die andere kopieren. Dann hast du auch keine Probleme. Möglicherweise musst du dazu aber noch an deiner Programmstruktur basteln.

Delbor 8. Mai 2017 22:09

AW: Gleiche Variablen-Namen
 
Hi DeddyH

Zitat:

Jetzt kann das Formular der Frame-Property eine TStrings-Instanz zuweisen, und der nutzt dann diese. Damit gibt es nur eine Instanz, aber beide haben Zugriff darauf.
Da gibts jetzt aber ein gewaltiges Missverständnis: Die Mainform darf/muss dem Pathfinderframe keinen String zuweisen. Die Aufgabe des Frames ist es ja gerade, die von seiner Komponente TFilesearcher gefundenen Pfade in einer Liste zu sammeln und diese nach aussen zu senden/von aussen auszulesen zu lassen. dieser Liste einen String von der Mainform, aus zuzuweisen.

Diese Procedure wird ausgeführt, wenn der Filesearcher einen Pfad gefunden hat:
Delphi-Quellcode:
procedure TSearchThread.DoOnMatchFound;
begin
  if Assigned(FOnMatchFound) then
    begin
      Lock;
      try
        FOnMatchFound(self, FPath, FSearchRec);
      finally
        UnLock;
      end;
    end;
end;
Das da gefeuerte Event wird im PathfinderFrame abgefangen:
Delphi-Quellcode:
procedure TPathFinderFrame.FileSearcher1MatchFound(Sender: TObject;
  const Path: string; const FileInfo: TSearchRec);
  var Complettpath, J: String;
begin
  if Assigned(FCurrentNode) then
  begin
    Complettpath := IncludeTrailingPathDelimiter(Path) +  FileInfo.Name;
    AddNewNode(FCurrentNode, FileInfo.Name, Complettpath,TSearchRecAnalyzer.IsDirectory(FileInfo));
  end;
end;
Und AddNewNode fügt dem Treeview einen neuen Knoten hinzu sowie FPathlist einen neuen String:
Delphi-Quellcode:
procedure TPathFinderFrame.AddNewNode(ParentNode: TTreeNode; const aCaption,
  aRealName: string; CanGetChildren: Boolean);
var
  Node: TTreeNode;
  NameRec: PNameRec;
begin
  Node := TVPathExplorer.Items.AddChild(ParentNode, aCaption);
  if CanGetChildren then
    begin
      Node.ImageIndex := 1;
      Node.SelectedIndex := 1;
      (* Dummy-Knoten anlegen *)
      TVPathExplorer.Items.AddChild(Node, 'dummy');
    end
  else
    begin
      Node.ImageIndex := 2;
      Node.SelectedIndex := 2;
      FPathlist.Add(aRealName); // <<===
    end;
  New(NameRec);
  NameRec^.RealName := aRealName;
  Node.Data := NameRec;
end;
In FPathlist stehen abschliessend alle in einem bestimmten Ordner gefundenen Dateien. Ausgelöst wird dder Event, wenn der Filesearcher seine Suche beendet hat:
Delphi-Quellcode:
procedure TPathFinderFrame.FileSearcher1ExecuteComplete(Sender: TObject);
  var LPathlist: TStringlist; LOrdner: String;
begin
  if Assigned(FCurrentNode) then
    FCurrentNode.Expand(false);
  if Assigned(FOnPathListEvent) then
    FOnPathListEvent(Sender, FOrdner, FPathlist);
end;
Der Eventtyp:
Delphi-Quellcode:
TPathListEvent = procedure(Sender:TObject; const FOrdner: String; const FPathlist: TStringList) of Object;
Wenn ich das richtig verstanden habe, müsste ich diesen Event jedesmal, wenn ein Pfad gefunden wird, feuern:
Delphi-Quellcode:
procedure TDingensFrame.SomeEvent(Param: string);
begin
  if Assigned(FPathList) then
    FPathList.Add(Param);
end;
Dieser Beispielcode erinnert mich allerdings sehr an diese Diskussion.
Damals hatte ich MapRules für eine normale Stringliste gehalten; reichlich spät kam ich dahinter, dass MapRules ene TCollection-Object ist und Add ein TCollectionitem-Objekt zurückliefert.
Im Gegensatz dazu ist nun FPathlist wirklich ein TStringlist-Objekt und Add die Methode, die der Liste einen Eintrag hinzufügt. Die Procedur müsste also so ausehen:
Delphi-Quellcode:
procedure TDingensFrame.SomeEvent(Pfad: string);
begin
  if Assigned(FPfad) then
    FPfad(Pfad);
end;
Und in TDingensMainForm:
procedure TDingensMainForm.DoSomeEvent(Pfad: string);
begin
Self.FPathlist.Add(Pfad);
end;
Das Problem, das ich da sehe, ist: woher weiss ich nun, wann der TDingensframe keine Pfade mehr sendet? Einfach nur zuzuwarten, ob innerhab einer gewissen Zeit noch was kommt, scheint mir sehr zweifelhaft.

Gruss
Delbor

Delbor 8. Mai 2017 22:54

AW: Gleiche Variablen-Namen
 
Hi Uwe Raabe
Zitat:

Das habe ich so nicht gesagt! Es muss dann schon geklärt werden, wer da dann was frei gibt.
Hmm... Und wie wird, bzw. kann dies geklärt werden? Indem der Compiler darüber informiert wird, welche der Variablen zu was gehört?
Genau das hat aber meine Frage veranlasst.

Zur Erinnerung: Meine bisherige Prozedur gibt die Liste direkt aus, ohne sie in einem Feld zwischenzuspeichern:
Delphi-Quellcode:
procedure TSQLiteTestMain.DoPathListEvent(Sender: TObject;
  const FOrdner: String; const FPathlist: TStringList);
begin
  Self.EdiFolder.Clear;
  Self.EdiFolder.Text := FOrdner;
  Self.LBxPathlist.Clear;
  Self.LBxPathlist.Items.AddStrings(FPathlist);
end;
Stattdessen soll nun der übergebene KonstantenParameter FPathlist an das private Feld TSQLiteTestMain.FPathlist übergeben werden. Das würde nach meinen bisherigen Vorstellungen etwa so ausehen:
Delphi-Quellcode:
procedure TSQLiteTestMain.DoPathListEvent(Sender: TObject;
  const FOrdner: String; const FPathlist: TStringList);
begin
  FPathlist.AddStrings(FPathlist);
end;
Und genau das dürfte unmöglich sein. Es sei denn...:
Delphi-Quellcode:
procedure TSQLiteTestMain.DoPathListEvent(Sender: TObject;
  const FOrdner: String; const FPathlist: TStringList);
begin
  Self.FPathlist.AddStrings(PathFinderFrame.FPathlist);
end;
Allerdings müsste so auch der Eventtyp angepasst werden: Statt
Delphi-Quellcode:
TPathListEvent = procedure(Sender:TObject; const FOrdner: String; const FPathlist: TStringList) of Object;
müsste dies heissen:
Delphi-Quellcode:
TPathListEvent = procedure(Sender:TObject; const FOrdner: String; const PathFinderFrame.FPathlist: TStringList) of Object;
Allerdings - ob sowas überhaupt möglich ist, ist mir nicht bekannt; ich denke eher nicht.
Wobei dann tatsächlich mein erster ansatz übrig bliebe:
Delphi-Quellcode:
procedure TPathFinderFrame.FileSearcher1ExecuteComplete(Sender: TObject);
  var LPathlist: TStringlist; LOrdner: String;
begin
  if Assigned(FCurrentNode) then
    FCurrentNode.Expand(false);
  if Assigned(FOnPathListEvent) then
  begin
    LPathList := TStringlist.Create;
    try
    LPathList.AddStrings(FPathlist);
    LOrdner := FOrdner;
    FOnPathListEvent(Sender, FOrdner, LPathlist);
    finally
      LPathList.Free;
    end;
  end;
end;
und in der Mainform:
Delphi-Quellcode:
procedure TSQLiteTestMain.DoPathListEvent(Sender: TObject;
  const FOrdner: String; const LPathlist: TStringList);
begin
  FPathlist.AddStrings(LPathlist);
end;
Gruss
Delbor

Uwe Raabe 8. Mai 2017 23:57

AW: Gleiche Variablen-Namen
 
Und was spricht gegen dies?
Delphi-Quellcode:
procedure TSQLiteTestMain.DoPathListEvent(Sender: TObject;
  const FOrdner: String; const FPathlist: TStringList);
begin
  Self.FPathlist.Assign(FPathlist);
end;

DeddyH 9. Mai 2017 06:28

AW: Gleiche Variablen-Namen
 
Jetzt muss ich aber mal nachhaken: wo genau wird diese Liste benötigt/angezeigt?

Ghostwalker 9. Mai 2017 07:00

AW: Gleiche Variablen-Namen
 
So wie ich das verstehe, wird die Liste im Mainform angzeigt.

Ich würde das so lösen (Code frei getippt):
Delphi-Quellcode:
   TOnComplete = TNotifyEvent;

   TPathfinderframe = Class...
   private
      fpathlist : TStringlist;
      fonComplete : TOnComplete;
     :
   published
     Property Pathlist : TStringlist read fpathlist write fpathlist;
     Property onComplete: TOnComplete read fonComplete write foncomplete;
     :
   end;
Bei der Suche selbst, innerhalb des Frames, wird die Stringliste erweitert. Beim Complete wird einfach das Event gefeuert und so dem Hauptformular bescheid gegeben, das die Liste neu ist. Anhand der Liste kann dann der Treeview entsprechend angezeigt werden.

Eine Instanz der Stringliste und eine Übergabe ist nicht notwendig.

Delbor 9. Mai 2017 07:24

AW: Gleiche Variablen-Namen
 
Hi zusammen

Vielen Dank, Uwe Raabe. An sowas habe ich weniger gedacht, da es mir zu wenig klar erschien. Aber klar - Self.FPathlist kann unmöglich der Parameter sein, womit klar wäre, welche der beiden Variablen an welche zugewiesen und von wem gelöscht wird.
Ohne die klare Adressierung mindestens der einen Variablen ist ja auch nicht wirklich klar, wer wem zugewiesen wird.

@DeddyH: FPathlist sammelt im PathfinderFrame die vom Filesearcher gefundenen Pfade. Hier im Test wird diese Liste von der Mainform abgearbeitet, soll aber in einem Datenmodul eingesetzt werden, um Daten - in diesem Fall Bilder - von der Festplatte in eine DB zu schreiben.

Den Pathfinderframe hatte ich ursrünglich unter dem Namen OpenfileDialog, bzw. OpenFileFrame entwickelt. Dieses Ding hat nur den grossen Fehler, dass es ausser gefundene Files anzuzeigen, auch noch andere, programmspezifische, Aufgaben erledigt. Allgemein sind da ddie Zugriffe des Frames und anderer Projektteile nicht sauber geregelt.
Na ja, das Ding hat schon einige Jährchen auf dem Buckel...

Gruss
Delbor

DeddyH 9. Mai 2017 07:38

AW: Gleiche Variablen-Namen
 
Und wozu brauchst Du dann eine 2. Instanz? Ich habe immer öfter den Eindruck, Du machst es Dir unnötig schwer.

Ghostwalker 9. Mai 2017 07:41

AW: Gleiche Variablen-Namen
 
@DeddyH

Jap...deshalb ja auch mein Lösungsansatz.

Sherlock 9. Mai 2017 07:41

AW: Gleiche Variablen-Namen
 
Ich schieße mal kurz unsachlich dazwischen: Wenn Du schon so einen Namen wie FPathList für ein Feld wählst, warum nicht auch aPathList für ein Argument? Zumindest wäre dann die Namensverwirrung im Titel sinnvoll aufgelöst

Ansonsten, schließe ich mich immer Uwe Raabes Meinung an... ;)

Sherlock

Delbor 9. Mai 2017 08:03

AW: Gleiche Variablen-Namen
 
Hi Ghostwalker
Ja, danke. Daran habe ich auch schon gedacht, mich dann aber für dieses Vorgehen entschieden, da ich ja auch noch ein Feld FOrdner habe, in dem der Name des Parentfolders enthält.

Zitat:

Die Sache mit dem Property habe ich mir auch überlegt. Einen Event müsste ich vom Frame aus aber so oder so abfeuern, da die Mainform ja nicht wissen kann, wann der PathfinderFrame die Liste (und damit das Listenproperty) neu bestückt. Das würde dann heissen, dass ich vom Frame aus einen TNotifierEvent abfeuere, den die Mainform empfängt und dabei dann das Listen-Property des Frames ausliest.
Klar könnte dieser Name aus einem Dateipfad herausgefiltert werden. Für die jetzige Vorgehensweise habe ich mich entschieden, weil Teile dieses Namens als DBName verwendet werden sollen. Und um nun alle Klarheiten zu beseitigen:
Ziel ist es, eine eingebettete SQLite-DB zu erstellen, die gerade mal eine Tabelle enthält,die ihrerseits nur einige wenige Felder aufweist. Die Aufgabe dieser DB wird es sein, RAWBild-Dateien und davon erstellte Bitmaps zu speichern. Diese DB soll auch Auskunft darüber geben, ob das Bitmap schon bearbeitet wurde.
Im Produktiveinsatz werden aus den RAW-Bildern nebst Bitmaps auch Thumbnails erstellt. Diese werden in meiner BilderDB (12 Tabellen, MySQL) gespeichert.

Gruss
Delbor

Delbor 9. Mai 2017 08:50

AW: Gleiche Variablen-Namen
 
Hi zusammen

@DeddyH:
Zitat:

Und wozu brauchst Du dann eine 2. Instanz? Ich habe immer öfter den Eindruck, Du machst es Dir unnötig schwer.
@Ghostwalker:
Zitat:

@DeddyH

Jap...deshalb ja auch mein Lösungsansatz.
Wenn Mainform (oder Datenmodul) einerseits und der Pathfinderframe andrerseits ihre eigene Instanz haben, sind die beiden voneinander unabhängig - sollte sich irgendwas in einer der beiden ändern, muss ich nicht mehrere Stellen bearbeiten, sondern nur diejenige, in der ein Event abgefangen wird.
Aber jetzt fällt mir auf:
Delphi-Quellcode:
   TOnComplete = TNotifyEvent;

   TPathfinderframe = Class...
   private
      fpathlist : TStringlist;
      fonComplete : TOnComplete;
     :
   published
     Property Pathlist : TStringlist read fpathlist write fpathlist;
     Property onComplete: TOnComplete read fonComplete write foncomplete;
     :
   end;
Durch das Property Pathlist lässt sich in einer Mainform oder einem Datenmodul genauso iterieren wie durch eine private Liste. Das widerspricht einzig etwas dem Schichtenmodell, wonach zwar die GUI (PathFinderFrame, Mainform) nach unten (Datenmodul) zugreifen sollen, nicht aber umgekehrt. Technisch ist es durchaus möglich.

Gruss
Delbor

Delbor 9. Mai 2017 11:25

AW: Gleiche Variablen-Namen
 
Hi zusammen

Eben hab ich versucht, Uwe Raabes Vorschlag umzusetzen. Der Empfänger des Events befindet sich bislang in der Mainform, und so wolllte ich ihn ins Datenmodul verlegen. Dazu kopierte ich die Prozedur in der Mainform, fügte sie im Datenmodul ein und liess sie per Shift/Control/C deklarieren. Anschliessend versuchte ich, die Variable FPathlist per Refactoring als privates Feld deklarieren zu lassen.
Da hat Delphi aber ganz schön gemeckert! Wie, das zeigt der Anhang.

Ich habe dann mal versucht, das Feld von Hand zu deklarieren. Das schien OK. So hab ich in der Empfängerprozedur einen Haltepunkt gesetzt. Aber als ich von da weitersteppen wollte, meckerte Delphi Gleich zweimal:
Zitat:

---------------------------
Im Projekt SQLiteTestProject.exe ist eine Exception der Klasse $C0000005 mit der Meldung 'access violation at 0x007e007d: read of address 0x0000007c' aufgetreten.
---------------------------
Und das 2. Mal beim weitersteppen mit F8:
Zitat:

---------------------------
Im Projekt SQLiteTestProject.exe ist eine Exception der Klasse EAccessViolation mit der Meldung 'Zugriffsverletzung bei Adresse 007E007D in Modul 'SQLiteTestProject.exe'. Lesen von Adresse 0000007C' aufgetreten.
---------------------------
FPathlist des Datenmoduls kann die AV nicht auslösen - die wird bei Datenmodul.Create erstellt. Und der Konstantenparameter FPathlist ist auch gut gefüllt. Weitere Objekte werden in der Prozedur nicht angesprochen:
Delphi-Quellcode:
procedure TDMLSQLite.DoPathListEvent(Sender: TObject;
  const FOrdner: String; const FPathlist: TStringList);
begin

  Self.FPathlist.Assign(FPathlist);
end;
So, wie ich das jetzt sehe, bleiben also 2 Lösungen:
  • Ich erstelle kurz vor dem Abfeuern des Events eine lokale Stringliste, gebe die dem Event mit und zerstöre sie bei Rückkehr wieder oder
  • Ich setze die Propertylösung ein und feuere einen TNotifier, wenn die Liste frisch gefüllt worden ist.

Gruss
Delbor

bra 9. Mai 2017 11:33

AW: Gleiche Variablen-Namen
 
Zitat:

Zitat von Delbor (Beitrag 1370731)
Delphi-Quellcode:
procedure TDMLSQLite.DoPathListEvent(Sender: TObject;
  const FOrdner: String; const FPathlist: TStringList);
begin

  Self.FPathlist.Assign(FPathlist);
end;

Private Variablen und Parameter mit demselben Namen, so etwas ist tückisch ohne Ende (wie auch schon erwähnt). Du solltest dir angewöhnen, Funktionsparamater anders zu benennen, die gängige Konvention ist "AName". Dann brauchst du auch den Self-Mist nicht.

Delphi-Quellcode:

class TDMLSQLite = ...
 private
   FPathlist: TStringList;
end;

procedure TDMLSQLite.DoPathListEvent(Sender: TObject; const AOrdner: String; const APathlist: TStringList);
var
  Pathlist: TStringList
begin
  FPathlist.Assign(APathlist);
end;

DeddyH 9. Mai 2017 11:35

AW: Gleiche Variablen-Namen
 
Vielleicht wäre es zielführender, Delphi erstmal links liegen zu lassen, Dich mit Bleistift und Papier hinzusetzen und einmal genau zu planen, wer was erzeugen/freigeben soll und wer worauf Zugriff haben muss. Ansonsten verschlimmbesserst Du Dein Programm am Ende immer weiter, bis gar nichts mehr funktioniert.

Uwe Raabe 9. Mai 2017 12:00

AW: Gleiche Variablen-Namen
 
Zitat:

Zitat von DeddyH (Beitrag 1370734)
Vielleicht wäre es zielführender, Delphi erstmal links liegen zu lassen, Dich mit Bleistift und Papier hinzusetzen und einmal genau zu planen, wer was erzeugen/freigeben soll und wer worauf Zugriff haben muss. Ansonsten verschlimmbesserst Du Dein Programm am Ende immer weiter, bis gar nichts mehr funktioniert.

:thumb::thumb::thumb: Du sprichst mir aus der Seele.

Delbor 9. Mai 2017 12:17

AW: Gleiche Variablen-Namen
 
Hi zusammen
@DeddyH:
Zitat:

Vielleicht wäre es zielführender, Delphi erstmal links liegen zu lassen, Dich mit Bleistift und Papier hinzusetzen und einmal genau zu planen, wer was erzeugen/freigeben soll und wer worauf Zugriff haben muss. Ansonsten verschlimmbesserst Du Dein Programm am Ende immer weiter, bis gar nichts mehr funktioniert.
Sorry, aber Papier und Bleistift meckern nicht. Wenn ich also was ungewöhnliches umsetzen will, schreibe ich kleine Testprogramme, die einen Bruchteil dessen tun,was im eigentlichen Programm getan werden soll. Auf diese Weise merke ich dann relativ schnell, ob etwas geht oder nicht.
Klar, ich hätte von Anfang an sehen können: Da sind zwei gleichnamige Variablen, die einander zugewiesen werden sollen. Mein Ansatz war ja, vor dem Abfeuern des Events eine weitere Stringliste anderen Namens zu erzeugen und die dann an die Datenmodul.Stringliste zuzuweisen.
Nur hätte ich dann für den gleichen Inhalt nicht nur 2 Instanzen der Liste gehabt, sondern temporär deren drei.

@bra:
Zitat:

Du solltest dir angewöhnen, Funktionsparamater anders zu benennen, die gängige Konvention ist "AName". Dann brauchst du auch den Self-Mist nicht.
Muss ich nicht, da ich es schon mache. Nur: bei Events ist das nicht möglich. Da muss der im Empfänger übergebene Parameter auch genau so heissen, wie der des Senders. Also:
Der Sender:
Delphi-Quellcode:
  if Assigned(FOnPathListEvent) then
    FOnPathListEvent(Sender, FOrdner, FPathlist);
und der Empfänger:
Delphi-Quellcode:
procedure TSQLiteTestMain.DoPathListEvent(Sender: TObject;
  const FOrdner: String; const FPathlist: TStringList);
begin
  Self.EdiFolder.Clear;
  Self.EdiFolder.Text := FOrdner;
  Self.LBxPathlist.Clear;
  Self.LBxPathlist.Items.AddStrings(FPathlist);
//  Self.FPathlist.Assign(FPathlist);
end;
Das erste, was ich versucht habe, war eben hier den Konstantenparameter anders zu benennen. Delphi meckerte das als unterschiedliche Deklaration an. Während ich dies schreibe, fällt mir auf, dass ich nicht versucht habe, die Liste nicht als Konstante zu übergeben. Aber das ändert an der Unterschiedlichen Deklaration nichts.
Wobei FPathList im PathfinderFrame zum Bleistift FFileList sein könnte. So sollte sich eine Kollision bei der Übergabe vermeiden lassen.

Gruss
Delbor

Uwe Raabe 9. Mai 2017 13:00

AW: Gleiche Variablen-Namen
 
Zitat:

Zitat von Delbor (Beitrag 1370746)
Nur: bei Events ist das nicht möglich. Da muss der im Empfänger übergebene Parameter auch genau so heissen, wie der des Senders.

Entschuldige, aber das ist Blödsinn! Die Deklaration eines Events ist die Stelle, an der die Parameternamen festgelegt werden. Da ist es vollkommen egal, ob der Parameter nun FPathList, APathList oder Hurz heißt. Wenn dir das FPathList nicht gefällt, dann benenne ihn einfach um. Das muss natürlich synchron im interface und implementation Teil geschehen.

Da die F-Notation schon von Feldern besetzt ist, bietet sich bei Parametern die A-Notation an - ist aber immer noch Geschmackssache.

Jumpy 9. Mai 2017 13:10

AW: Gleiche Variablen-Namen
 
Zitat:

Zitat von Delbor (Beitrag 1370746)
Das erste, was ich versucht habe, war eben hier den Konstantenparameter anders zu benennen. Delphi meckerte das als unterschiedliche Deklaration an.

Das heißt eigentlich nur, das du es im Interface-Teil anders deklarierst als im Implementaion-Teil!

Sherlock 9. Mai 2017 13:54

AW: Gleiche Variablen-Namen
 
Auf mich will ja keiner hören... seufz.

Sherlock

haentschman 9. Mai 2017 16:12

AW: Gleiche Variablen-Namen
 
[OT]
:P
Patient: Alle ignorieren mich! Arzt: Der nächste bitte...

Willkommen im Club. :zwinker:
[/OT]

Zitat:

Und wozu brauchst Du dann eine 2. Instanz? Ich habe immer öfter den Eindruck, Du machst es Dir unnötig schwer.
...das denke auch. :?

Delbor 9. Mai 2017 16:26

AW: Gleiche Variablen-Namen
 
Hi zusammen

@ Jumpy
Zitat:

Das heißt eigentlich nur, das du es im Interface-Teil anders deklarierst als im Implementaion-Teil!
Ups - da hab ich jetzt nicht daran gedacht!
Ich habe mich hierauf gestützt - von Namensgleicheit ist hier nicht die Rede.
Ein Zitat daraus:
Zitat:

In beiden Fällen müssen im Aufruf Parameter übergeben werden, die in der Reihenfolge und im Typ den in der Parameterliste der Routine angegeben Parametern entsprechen
Also müsste der Zielparameter an z.B. erster Stelle vom Typ des Quellparameters sein, auch wenn er anders heisst.

Als ich versuchte, den Namen des übergeben Listen-Parameters zu ändern und Delphi meckerte wegen unterschiedlicher Deklaration, dachte ich allerdings an die Deklaration des Events und nicht an diejenige der Empfängerroutine. Und da müssen in der Deklaration und in der Implementierung nicht nur Reihenfolge und Tip stimmen, sondern auch die Parameterbezeichner.

@Uwe Raabe
Zitat:

Entschuldige, aber das ist Blödsinn! Die Deklaration eines Events ist die Stelle, an der die Parameternamen festgelegt werden.
Sorry, aber ich fürchte, du hast mich fallsch verstanden. Um es mal anders auszudrücken:
Delphi-Quellcode:
procedure Tfoo.xxx
begin
  GetNamen(Strasse, Hausnummer)
end

function Getnamen(Street, Number)
Begin
  End
End;
Natürlich müssen die Deklarationen jeder der beiden Methoden dabei gleich lauten und die Reihenfolge und Typen der Parameter übereinstimmen.

Interessant ist jetzt: Im Datenmodul Heisst die Liste jetzt anders. Trotzdem gibts die beiden schon gepostetn Fehlermeldungen. Andrerseits funktioniert folgendes problemlos:
Delphi-Quellcode:
procedure TDMLSQLite.DoPathListEvent(Sender: TObject;
  const FOrdner: String; const FPathlist: TStringList);
begin
//  FFileList.AddStrings (FPathlist);  //<<=== löst die bekannten Fehlermeldungen aus
  SQLiteTestMain.LBxPathlist.Items.AddStrings(FPathlist);  //<<== Kein Problem
end;
@Sherlock:
Zitat:

Auf mich will ja keiner hören... seufz.
Ich guck mir deinen Beitrag gleich nochmal an!

Gruss
Delbor

haentschman 9. Mai 2017 16:34

AW: Gleiche Variablen-Namen
 
Hallöle...8-)
Zitat:

Entschuldige, aber das ist Blödsinn! Die Deklaration eines Events ist die Stelle, an der die Parameternamen festgelegt werden.
...was Uwe meint ist, das der Name Schall und Rauch ist. Der kann meinetwegen auch MeinGelbesBlubb heißen. Wichtig ist der Inhalt. :thumb:
Schreib mal die Eventdeklaration.

Delbor 9. Mai 2017 16:36

AW: Gleiche Variablen-Namen
 
Hi Sherlock
Zitat:

Ich schieße mal kurz unsachlich dazwischen: Wenn Du schon so einen Namen wie FPathList für ein Feld wählst, warum nicht auch aPathList für ein Argument? Zumindest wäre dann die Namensverwirrung im Titel sinnvoll aufgelöst
Der Grund ist:
Nenne ich den übergebenen ListenParameter im Empfänger AList, muss er auch bei der Eventdeklaration so heissen. Ich habe im Frame die Deklaration der Liste mal probeweise nach Public verschoben. Das hatte jedoch keine Auswirkungen - wenn, dann hätte ich erwartet, dass von den angesprochenen 2 Fehlermeldungen eine ausbleibt.

Gruss
Delbor

haentschman 9. Mai 2017 16:40

AW: Gleiche Variablen-Namen
 
Zitat:

Nenne ich den übergebenen ListenParameter im Empfänger AList, muss er auch bei der Eventdeklaration so heissen.
...korrekt.

Über welche Fehlermeldungen reden wir? Screenshot. :wink:

Aviator 9. Mai 2017 16:42

AW: Gleiche Variablen-Namen
 
Zitat:

Zitat von Delbor (Beitrag 1370774)
@Uwe Raabe
Zitat:

Entschuldige, aber das ist Blödsinn! Die Deklaration eines Events ist die Stelle, an der die Parameternamen festgelegt werden.
Sorry, aber ich fürchte, du hast mich fallsch verstanden. Um es mal anders auszudrücken:
Delphi-Quellcode:
procedure Tfoo.xxx
begin
  GetNamen(Strasse, Hausnummer)
end

function Getnamen(Street, Number)
Begin
  End
End;
Natürlich müssen die Deklarationen jeder der beiden Methoden dabei gleich lauten und die Reihenfolge und Typen der Parameter übereinstimmen.

Damit das jetzt nicht missverstanden wird, mache ich mal ein etwas ausführlicheres Beispiel:

Delphi-Quellcode:
type
  // Deklaration des Events
  TMyEvent = procedure(Street: string; Country: string) of object;
 
  TMyClass = class
  private
    FOnReport: TMyEvent;
  public
    procedure DoSomethingAndReport();
    property OnReport: TMyEvent read FOnReport write FOnReport;
  end;
 
  TForm1 = class(TForm)
  private
    procedure ReportHandler(Street: string; Country: string);
  end;
 
 
 implementation
 
 procedure TMyClass.DoSomethingAndReport();
 var
   tmpStreet, tmpCountry: string;
 begin
   tmpStreet := GetStreet(); // Irgendeine Methode ausführen
   tmpStreet := GetCountry(); // Irgendeine Methode ausführen
   
   if Assigned(FOnReport) then
     FOnReport(tmpStreet, tmpCountry); // Hier wird das Event ausgelöst
 end;
 
 
 // EventHandler für TMyClass.OnReport
 // Hier könnten die Parameter Bezeichner sogar schon von der Event-Deklaration abweichen
 // Wichtig sind die Datentypen. Die müssen in Reihenfolge und Typ mit der Event-Deklaration übereinstimmen
 procedure TForm1.ReportHandler(Street: string; Country: string);
 begin
   ShowMessage(Street + sLineBreak + Country);
 end;


Alle Zeitangaben in WEZ +1. Es ist jetzt 04:26 Uhr.
Seite 1 von 2  1 2      

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