Verzweigung je nach Sender:TObject

Für Fragen zur Programmiersprache auf welcher Lazarus aufbaut
Benutzeravatar
photor
Beiträge: 443
Registriert: Mo 24. Jan 2011, 21:38
OS, Lazarus, FPC: Arch Linux: L 2.2.6 FPC 3.2.2 (Gtk2)
CPU-Target: 64Bit

Verzweigung je nach Sender:TObject

Beitrag von photor »

Hallo Forum,

wiedermal eine Frage nach einer eleganteren Lösung für meinen Holzhammer-Code: in meinem Programm gibt es einen Bereich, in dem etliche Parameter angezeigt und geändert werden können (organisiert in mehreren Tabs). Nun möchte ich nicht für jedes TEdit eine neue OnExit-Funktion schreiben, sonder in einer Funktion nach dem betreffenden TEdit-Feld unterscheiden. Das funktioniert im Moment mittels if ... else if ... else if ...-Kette (siehe Beispiel). Das scheint mir aber eher unelegant.

Code: Alles auswählen

 
procedure TForm1.EditParameterOnExit(Sender : TObject);
begin
  with RoadLoadData do
   { Tab: Information }
    if Sender = EditInfoName then
      Name := EditInfoName.Text    // ToDo: max. Stringlaenge abfangen!!
    { Tab: Geometry }
    else if Sender = EditBikeWeight then
      //Gewicht := StrToFloat(Sender.Text)    // das tut nicht
      Gewicht := StrToFloat(EditBikeWeight.Text)
    else if Sender = EditCoGx then
      sx := StrToFloat(EditCoGx.Text)
    else if Sender = EditCoGy then
      sy := StrToFloat(EditCoGy.Text)
    else if Sender = EditFrontArea then
[...]
 

Mittels case geht es natürlich nicht. Die TEdit-Felder enthalten double, integer oder Text-Felder. Dannach könnte man vielleicht "vorsortieren". Hat noch jemand andere Ideen?

Danke,

Photor


PS: gibt es eigentlich Quellen für solche eleganten Programmier"tricks"/lösungen (also keinen Style Guide)? Würde gerne mehr darüber lernen.

Benutzeravatar
theo
Beiträge: 10468
Registriert: Mo 11. Sep 2006, 19:01

Re: Verzweigung je nach Sender:TObject

Beitrag von theo »

Man könnte sie am Tag oder am Name unterscheiden und dann Case anwenden:

Code: Alles auswählen

 case TEdit(Sender).Tag of        
oder
case TEdit(Sender).Name of
 

mschnell
Beiträge: 3444
Registriert: Mo 11. Sep 2006, 10:24
OS, Lazarus, FPC: svn (Window32, Linux x64, Linux ARM (QNAP) (cross+nativ)
CPU-Target: X32 / X64 / ARMv5
Wohnort: Krefeld

Re: Verzweigung je nach Sender:TObject

Beitrag von mschnell »

Ich habe den Code jetzt nicht vorliegen, aber ich weiß dass mein Sohn einmal ein "Array of TClass" gemacht hat. In den Elementen kann dann ohne Umwege der Type (vermutlich eine ID) gespeichert werden (geht nur für Objekte). Dann könnte man in einer Schleife den Type von Sender abfragen. Ob damit auch "case" geht, weiß ich nicht, halte ich aber für möglich.

-Michael

mschnell
Beiträge: 3444
Registriert: Mo 11. Sep 2006, 10:24
OS, Lazarus, FPC: svn (Window32, Linux x64, Linux ARM (QNAP) (cross+nativ)
CPU-Target: X32 / X64 / ARMv5
Wohnort: Krefeld

Re: Verzweigung je nach Sender:TObject

Beitrag von mschnell »

Code: Alles auswählen

 
unit Unit1;
 
{$mode objfpc}{$H+}
 
interface
 
uses
  Classes, SysUtils, FileUtil, Forms, Controls, Graphics, Dialogs, StdCtrls;
 
type
 
  { TForm1 }
 
  TForm1 = class(TForm)
    Button1: TButton;
    procedure FormCreate(Sender: TObject);
  private
    { private declarations }
    procedure do1;
    procedure do2;
  public
    { public declarations }
  end;
 
var
  Form1: TForm1;
 
implementation
 
{$R *.lfm}
 
{ TForm1 }
 
Type
  MyClasses = (aTForm1, aTButton);
  TAType = Array [MyClasses] of TClass;
 
var
AType : TAType;
T: TClass;
i, j: MyClasses;
 
procedure TForm1.FormCreate(Sender: TObject);
begin
{ Schön wärs:
  case Sender.ClassType of
    TForm1.ClassType: do1;
    TButton.ClassType: do2;
  end;
}

  OnClick:=@FormCreate;
  Button1.OnClick:=@FormCreate;
 
  AType[aTForm1] := TForm1.ClassType;
  AType[aTButton] := TButton.ClassType;
  T := Sender.ClassType;
 
  for i := Low(AType) to High(AType) do begin
    if AType[i] = T then begin
      j := i;
      Break;
    end;
  end;
 
  case j of
   aTForm1: do1;
   aTButton: do2;
  end;
 
 
end;
 
procedure TForm1.do1;
begin
  Caption:=Form1.Name;
end;
 
procedure TForm1.do2;
begin
  Caption:=Button1.Name;
end;
 
end.
 

mschnell
Beiträge: 3444
Registriert: Mo 11. Sep 2006, 10:24
OS, Lazarus, FPC: svn (Window32, Linux x64, Linux ARM (QNAP) (cross+nativ)
CPU-Target: X32 / X64 / ARMv5
Wohnort: Krefeld

Re: Verzweigung je nach Sender:TObject

Beitrag von mschnell »

Oder so (ohne Schleife im User-Code):

Code: Alles auswählen

 
unit Unit1;
 
{$mode objfpc}{$H+}
 
interface
 
uses
  Classes, SysUtils, FileUtil, Forms, Controls, Graphics, Dialogs, StdCtrls;
 
type
 
  { TForm1 }
 
  TForm1 = class(TForm)
    Button1: TButton;
    procedure FormCreate(Sender: TObject);
  private
    { private declarations }
    procedure do1;
    procedure do2;
  public
    { public declarations }
  end;
 
var
  Form1: TForm1;
 
implementation
 
{$R *.lfm}
 
{ TForm1 }
 
Type
  MyClasses = (aTForm1, aTButton);
 
procedure TForm1.FormCreate(Sender: TObject);
var
  l: TList;
begin
  OnClick:=@FormCreate;
  Button1.OnClick:=@FormCreate;
 
{ Schön wärs:
  case Sender.ClassType of
    TForm1.ClassType: do1;
    TButton.ClassType: do2;
  end;
}

 
 
  l := Tlist.Create;
  l.Add(TForm1.ClassType);
  l.Add(TButton.ClassType);
 
 
/////////// nur das muss in den Event-Handler ////////////////
  case MyClasses(l.IndexOf(Sender.ClassType)) of
   aTForm1: do1;
   aTButton: do2;
  end;
//////////////////////////////////////////////////////////
 
 
  l.Free;
 
end;
 
procedure TForm1.do1;
begin
  Caption:=Form1.Name;
end;
 
procedure TForm1.do2;
begin
  Caption:=Button1.Name;
end;
 
end.
 

Michl
Beiträge: 2505
Registriert: Di 19. Jun 2012, 12:54

Re: Verzweigung je nach Sender:TObject

Beitrag von Michl »

mschnell hat geschrieben:Type von Sender abfragen
Das war aber gar nicht die Frage.

Code: Alles auswählen

type
  TLiveSelection = (lsMoney, lsChilds, lsTime);
  TLive = Array[0..1] of TLiveSelection; 

mschnell
Beiträge: 3444
Registriert: Mo 11. Sep 2006, 10:24
OS, Lazarus, FPC: svn (Window32, Linux x64, Linux ARM (QNAP) (cross+nativ)
CPU-Target: X32 / X64 / ARMv5
Wohnort: Krefeld

Re: Verzweigung je nach Sender:TObject

Beitrag von mschnell »

Michl hat geschrieben:
mschnell hat geschrieben:Type von Sender abfragen
Das war aber gar nicht die Frage.

Die Instanz abzufragen ist mit

case TList.IndexOf(Sender)
...

natürlich trivial.

-Michael

Benutzeravatar
photor
Beiträge: 443
Registriert: Mo 24. Jan 2011, 21:38
OS, Lazarus, FPC: Arch Linux: L 2.2.6 FPC 3.2.2 (Gtk2)
CPU-Target: 64Bit

Re: Verzweigung je nach Sender:TObject

Beitrag von photor »

Moin,

Ich wollte mich kurz melden und "Danke!" schon mal für die Antworten. Komme leider erst am WE wieder zum Testen (ist halt ein Hobby-Projekt). Parallel recherchiere ich weiter im Netz.

Ciao,

Photor

Benutzeravatar
photor
Beiträge: 443
Registriert: Mo 24. Jan 2011, 21:38
OS, Lazarus, FPC: Arch Linux: L 2.2.6 FPC 3.2.2 (Gtk2)
CPU-Target: 64Bit

Re: Verzweigung je nach Sender:TObject

Beitrag von photor »

Hallo Forum,

konnte zwischendurch etwas zu den "Tags" lesen. Scheint mir bislang das einleuchtenste Konzept zu sein.
  • Die Tags vergebe ich selbst und es sind einfach integer, richtig?
  • ich kann sie so sinnvoll gruppieren (oder müssen die Tags kontinuierlich vergeben werden)
  • sie sind mit case recht einfach dannach verzweigen

Oder gibt es Nachteile?

Ciao,

Photor

Benutzeravatar
theo
Beiträge: 10468
Registriert: Mo 11. Sep 2006, 19:01

Re: Verzweigung je nach Sender:TObject

Beitrag von theo »

Ja
Ja (Nein)
Ja
Nein

wp_xyz
Beiträge: 4869
Registriert: Fr 8. Apr 2011, 09:01

Re: Verzweigung je nach Sender:TObject

Beitrag von wp_xyz »

photor hat geschrieben:Oder gibt es Nachteile?

Naja... Ich finde die IF-Kette ganz oben sehr übersichtlich und kompakt, da ist alles in einer Prozedur und man weiß sofort, was passiert. Wenn du die Tags verwendest, musst du sie im Objektinspektor setzen und hast damit zwei Orte, wo sie verwendet werden, im Objektinspektor und in der Event-Prozedur. Das finde ich erheblich unübersichtlicher und auch fehlerträchtig, weil du nicht auf einen Blick sehen kannst, ob die Tags richtig gesetzt sind, sondern zur Prüfung der Tags alle Controls durchklicken musst.

Requion
Beiträge: 106
Registriert: Mi 3. Feb 2016, 09:39
OS, Lazarus, FPC: Linux(Arch Linux(+ARM)/Minibian) (L 1.6.0 FPC 3.0.0)
CPU-Target: 32/64Bit,ARM(RPi)
Wohnort: nahe Grimma

Re: Verzweigung je nach Sender:TObject

Beitrag von Requion »

wp_xyz hat geschrieben:
photor hat geschrieben:Oder gibt es Nachteile?

Naja... Ich finde die IF-Kette ganz oben sehr übersichtlich und kompakt, da ist alles in einer Prozedur und man weiß sofort, was passiert. Wenn du die Tags verwendest, musst du sie im Objektinspektor setzen und hast damit zwei Orte, wo sie verwendet werden, im Objektinspektor und in der Event-Prozedur. Das finde ich erheblich unübersichtlicher und auch fehlerträchtig, weil du nicht auf einen Blick sehen kannst, ob die Tags richtig gesetzt sind, sondern zur Prüfung der Tags alle Controls durchklicken musst.

Wobei das ab einer bestimmten Anzahl dann auch irgendwann unübersichtlich wird.
Aber man könnte die Tags ja auch in einer Prozedur setzen. Da kann man das dann auch gleich schön mit Kommentaren gruppieren/dokumentieren.
Mfg Requion

Das beste an Standards ist, dass es so viele davon gibt.

wp_xyz
Beiträge: 4869
Registriert: Fr 8. Apr 2011, 09:01

Re: Verzweigung je nach Sender:TObject

Beitrag von wp_xyz »

Warum nimmst du nicht die Komponentennamen in eine Case-Anweisung? Wenn du schon die IF-Kette nicht magst, ist das 1000mal klarer als die Tag-Variante:

Code: Alles auswählen

procedure TForm1.EditParameterEditingDone(Sender: TObject);
begin
  case TComponent(Sender).Name of
    'EditInfoName'   : RoadLoadData.Name := TEdit(Sender).Text;
    'EditBikeWeight' : RoadLoadData.Gewicht := StrToFloat(TEdit(Sender).Text);
    // etc.
  end;
end;

Das hat theo übrigens schon ganz oben vorgeschlagen.

Requion
Beiträge: 106
Registriert: Mi 3. Feb 2016, 09:39
OS, Lazarus, FPC: Linux(Arch Linux(+ARM)/Minibian) (L 1.6.0 FPC 3.0.0)
CPU-Target: 32/64Bit,ARM(RPi)
Wohnort: nahe Grimma

Re: Verzweigung je nach Sender:TObject

Beitrag von Requion »

Case Anweisungen schlucken doch keine strings oder? Man könnte sich aber ein set mit den Namen machen und das dann entsprechend in das case packen.

Möglichkeiten gibt es da viele, aber ich meine gelesen zu haben das die Tags eben dafür implementiert worden sind. Den link dazu hab ich aber nicht mehr.
Mfg Requion

Das beste an Standards ist, dass es so viele davon gibt.

Benutzeravatar
m.fuchs
Lazarusforum e. V.
Beiträge: 2636
Registriert: Fr 22. Sep 2006, 19:32
OS, Lazarus, FPC: Winux (Lazarus 2.0.10, FPC 3.2.0)
CPU-Target: x86, x64, arm
Wohnort: Berlin
Kontaktdaten:

Re: Verzweigung je nach Sender:TObject

Beitrag von m.fuchs »

Requion hat geschrieben:Case Anweisungen schlucken doch keine strings oder?

CASE mit Strings wird seit FPC 2.6.0 unterstützt.
Software, Bibliotheken, Vorträge und mehr: https://www.ypa-software.de

Antworten