GUI Design und Objektliste

Für Fragen von Einsteigern und Programmieranfängern...
Antworten
charlytango
Beiträge: 843
Registriert: Sa 12. Sep 2015, 12:10
OS, Lazarus, FPC: Laz stable (2.2.6, 3.x)
CPU-Target: Win 32/64, Linux64
Wohnort: Wien

GUI Design und Objektliste

Beitrag von charlytango »

Hallo allseits !

Falls das Thema woanders besser passt, bitte ich die Admins es zu verschieben.

Es geht um ein GUI Design für eine Applikation. Nennen wir sie der Einfachheit halber eine Kundenverwaltung.
Die klassischen Funktionen neben dem Hauptformular sind:
- Kunden suchen
- Kunden bearbeiten

Aus der Ergebnisliste der Kundensuche sollen Formulare zur Kundenbearbeitung aufgerufen werden.
Diese Formulare (und auch Formulare von anderen Fomulartypen) sollen nicht modal aufgerufen und angezeigt werden.

Im Gegensatz zu modalem Design hat der Anwender mehr Möglichkeiten (z.B. zwei Kunden im Fenster direkt gegenüber zu stellen), allerdings braucht es dann auch eine Verwaltung der existierenden Formulare, um sie sauber zu schließen und etwaige offene Speichervorgänge anzumahnen oder auch um bereits existierende Formulare nur in den Vordergrund zu bringen.

Meine Frage geht dahin welches die beste Methode zum Verwalten heterogener Objekte in Form einer "Liste" ist.

A.) mit TObjectlist

B.) mit TStringlist

C.) andere Variante?

Zur Verwaltung heterogener Objekte/Formulare müsste in der Liste ein Objekttyp und eine ID zum Objekt mitgeführt werden, um es schnell in einer Liste auffinden zu können. Als Elementanzahl könnte man die Liste nach oben hin begrenzen, wenn die Performance leidet, ich gehe mal von einer durchschnittlichen Objektanzahl von 20-50 aus.

Variante A mit TObjectlist bringt außer dem Suchen bestimmter Objekte alles mit, auch das freigeben aller in der Liste enthaltenen Objektelemente (evtl kann man im OnCloseQuery eines Formulares abfangen ob geänderte Daten zu speichern sind)

Ich bitte um Erfahrungen und Empfehlungen für unterschiedliche Verfahren.

Danke im Voraus

Benutzeravatar
m.fuchs
Lazarusforum e. V.
Beiträge: 2640
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: GUI Design und Objektliste

Beitrag von m.fuchs »

Was sind denn das für heterogene Objekte? Unterscheiden sie sich stark oder könnten sie alle von einer Basisklasse ableiten. Im letzteren Fall brauchst du eventuell den Objekttyp gar nicht, sondern kannst alles über Vererbung und Polymorphie lösen. Dann wäre eine generische Liste deines Basistyps eine Lösung.
Software, Bibliotheken, Vorträge und mehr: https://www.ypa-software.de

charlytango
Beiträge: 843
Registriert: Sa 12. Sep 2015, 12:10
OS, Lazarus, FPC: Laz stable (2.2.6, 3.x)
CPU-Target: Win 32/64, Linux64
Wohnort: Wien

Re: GUI Design und Objektliste

Beitrag von charlytango »

m.fuchs hat geschrieben:Was sind denn das für heterogene Objekte? Unterscheiden sie sich stark oder könnten sie alle von einer Basisklasse ableiten. Im letzteren Fall brauchst du eventuell den Objekttyp gar nicht, sondern kannst alles über Vererbung und Polymorphie lösen. Dann wäre eine generische Liste deines Basistyps eine Lösung.


Ich hab mir deinen Ansatz auch angesehen :wink:

Es geht um quasi alle Formulare die in einer Applikation so vorkommen können.
Suchformulare, Eingabeformulare (sagen wir für Stammdaten aller Art), Reportformulare und was weiß ich noch alles.

Mit deinem Ansatz könnte ich für jeden Objekttyp eine eigene Liste führen, was mir aber noch nicht die Suche nach einem bestimmten (Formular-) Objekt abdeckt. Bei der Suche in einer nicht von außen identifizierbaren Objektliste (also eine Suche bei der ich das Objekt "angreifen" muss, um z. B. eine Property auszulesen) wäre ich vermutlich auch langsamer (oder etwa nicht?).

Kann auch sein dass ich da etwas nicht verstehe ???
Die Formulare sind praktisch alle von TForm abgeleitet, sonst aber sehr unterschiedlich und mittels Lazarus-GUI erzeugt.

Benutzeravatar
m.fuchs
Lazarusforum e. V.
Beiträge: 2640
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: GUI Design und Objektliste

Beitrag von m.fuchs »

Ah, ich verstehe. Es geht dir um die Formulare, nicht um die angezeigten Datenobjekte.
Nun gut.

charlytango hat geschrieben:um sie sauber zu schließen und etwaige offene Speichervorgänge anzumahnen

Dafür ist es ja nicht wichtig, um was für ein Formular es sich handelt. Eine Liste vom Typ der Basisklasse würde ausreichen.

charlytango hat geschrieben:auch um bereits existierende Formulare nur in den Vordergrund zu bringen

Auch hier ist eventuell die Art des Formulars uninteressant. Wenn deine Datensätze datenbankweit eindeutig identifizierbar sind. Zum Beispiel per GUID (https://de.wikipedia.org/wiki/Globally_ ... Identifier). Dann brauchst du zum geöffneten Formular nur den Datensatz-Identifikator abzulegen. Zum Beispiel in einer generischen Map:

Code: Alles auswählen

TDataFormHashTable = specialize TFPGMap<String, TForm>;

Wenn ein Datensatz aufgerufen wird, schaust du in der Map nach ob schon ein Eintrag mit der ID drin ist. In diesem Fall nimmst du das bestehende Formular und zeigst es an.
Software, Bibliotheken, Vorträge und mehr: https://www.ypa-software.de

charlytango
Beiträge: 843
Registriert: Sa 12. Sep 2015, 12:10
OS, Lazarus, FPC: Laz stable (2.2.6, 3.x)
CPU-Target: Win 32/64, Linux64
Wohnort: Wien

Re: GUI Design und Objektliste

Beitrag von charlytango »

Yep -- es geht um Formulare, die je nach Usersinstellung entweder (nach MDI-Vorbild) frei schwebend angezeigt werden oder auch per TPagecontrol oder TTabControl in ein Hauptformular eingedockt werden sollen.

Leider sind die Datensätze nicht datenbankweit eindeutig per GUID identifizierbar sondern nur als Tabellenname samt deren Primary Key (integer, autoincrement)

Ich habe mir nochmal deine Lösung angesehen, die verwendet eine TFPObjectList.

Ich könnte also eine Liste gleichartiger Elemente so realisieren dass ich ein Formular (TBaseForm) erstelle und dieses mit den nötigen Properties zum Identifizieren des dann gesuchten Formulars ausstatte.

Code: Alles auswählen

type
  TBaseForm= class(TForm)
    Label1: TLabel;
  private
    FiID: string;
    FsTyp: string;
    procedure SetiID(AValue: string);
    procedure SetslTyp(AValue: string);
  public
     property psTyp:string read FsTyp write SetslTyp;
     property piID:string read FiID write SetiID;
  end;                                             
 


Vom Formular TBaseForm leite ich dann alle meine Arbeitsformulare ab.

Code: Alles auswählen

 
type
  TMeinFormular1 = class(TBaseForm)
 


TFPObjectList verwaltet (im Gegensatz zu TObjectList) lt Wiki Objekte ohne "Notification" -- was ist damit gemeint ?

In TFPObjectList werden also Objekte und nicht nur die Pointer darauf verwaltet.
Ein Formular hinzuzufügen würde also so funktionieren:

Code: Alles auswählen

 
//Deine Objektliste erzeugen
oWindowList := TWindowsList.Create
 
//Neues Formular erzeugen und der Objektliste hinzufügen
procedure TfrmMain.Button1Click(Sender: TObject);
var
   f1:TMeinFormular1;
begin
  f1:=TMeinFormular1.Create(Nil);
  f1.psTyp:='Kunde'//Typ festlegen
  f1.piID:=1;            //ID festlegen
  oWindowList.Add(tf1);
end;
 


Da tauchen aber auch noch Fragen auf:
Das Objekt f1 wird erzeugt und der Liste hinzugefügt. Nachdem das Objekt selbst in der Liste verwaltet wird, sollte es eigentlich kopiert werden, oder ?

Und muss dann das quasi temporär erzeugte Objekt f1 nicht noch zerstört werden?

Deine Funktion dazu:
function Add(AObject: TForm): Integer;

Folgt man der Objekthierarchie wird das im Objekt TFPObjectList als

Code: Alles auswählen

Function TFPObjectList.Add(AObject: TObject): Integer; {$ifdef CLASSESINLINE}inline;{$endif}
begin
  Result:=FList.Add(AObject);
end;


realisiert und dort wiederum als

Code: Alles auswählen

 
function TFPList.Add(Item: Pointer): Integer;
begin
  if FCount = FCapacity then
    Self.Expand;
  FList^[FCount] := Item;
  Result := FCount;
  FCount := FCount + 1;
end;


endet. Leider setzt da mein Verständnis aus -- ist das nun noch das Objekt oder nur "mehr" ein Pointer drauf ?

LG

Benutzeravatar
m.fuchs
Lazarusforum e. V.
Beiträge: 2640
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: GUI Design und Objektliste

Beitrag von m.fuchs »

charlytango hat geschrieben:Leider sind die Datensätze nicht datenbankweit eindeutig per GUID identifizierbar sondern nur als Tabellenname samt deren Primary Key (integer, autoincrement)

Auch damit wären sie eindeutig identifizierbar:

Code: Alles auswählen

var
  UniqueId: String;
begin
  UniqueId := TableName + ':' + IntToStr(Id);
end;
Software, Bibliotheken, Vorträge und mehr: https://www.ypa-software.de

charlytango
Beiträge: 843
Registriert: Sa 12. Sep 2015, 12:10
OS, Lazarus, FPC: Laz stable (2.2.6, 3.x)
CPU-Target: Win 32/64, Linux64
Wohnort: Wien

Re: GUI Design und Objektliste

Beitrag von charlytango »

m.fuchs hat geschrieben:
charlytango hat geschrieben:Leider sind die Datensätze nicht datenbankweit eindeutig per GUID identifizierbar sondern nur als Tabellenname samt deren Primary Key (integer, autoincrement)

Auch damit wären sie eindeutig identifizierbar:

Code: Alles auswählen

var
  UniqueId: String;
begin
  UniqueId := TableName + ':' + IntToStr(Id);
end;



Du hast völlig recht -- was mir nicht ganz klar ist:

wo liegen die Vorteile einer TFPGMap

Code: Alles auswählen

TDataFormHashTable = specialize TFPGMap<String, TForm>;


die du mir empfohlen hast, gegenüber einer TFPObjectList

Code: Alles auswählen

TWindowlist = class(TFPObjectList)


die du in deinem Code verwendest ?

PS: dein Code aus dem Generator funktioniert fein, danke !

Antworten