[gelöst] Formular Grid-Layout

Rund um die LCL und andere Komponenten
Korkenkrone
Beiträge: 33
Registriert: Sa 18. Sep 2010, 20:33
OS, Lazarus, FPC: OpenSUSE 11.3 (L 0.9.28.2 Beta FPC 2.2.4)
CPU-Target: x86-64

[gelöst] Formular Grid-Layout

Beitrag von Korkenkrone »

Guten Abend,

Kann mir jemand von euch sagen, welche Werkzeuge man benutzen kann, um ein Grid-Layout für ein Formular zu erstellen, dass sich dynamisch den jeweiligen Themes/Schriftarten anpasst? Ich habe hier in einem anderen Thread gelesen, dass sich mit ChildSizing ein Grid-Layout erstellen lässt, man aber die Reihenfolge der Controls selbständig festlegen muss, da sonst die Labels immer vorne stehen (was sich ärgerlicherweise bestätigt hat. Wieso ist das so?). Wie mache ich das bei dynamisch erstellten Controls selbst? Ein Formular mit Label + Edit/ComboBox/CheckBox auf jeder Zeile sollte doch wirklich ein häufiges Problem sein, daher denke ich nicht, dass ich Position und Größe der Controls selbst verwalten muss.

Ich habe auch schon daran gedacht die Elemente vorher einzeln in einen Container zu packen, damit Lazarus nciht mehr zwischen Label und Edit unterscheiden kann, aber das ist ja nun nicht Sinn der Sache an der LCL vorbei zu arbeiten, oder doch? Wie müsste so ein Container aussehen und welche Komponente sollte ich dafür verwenden?

Derzeit habe ich es so versucht:

Code: Alles auswählen

procedure TFormMain.GenerateControls;
var
  I: Integer;
begin
  For I := 1 to 10 do begin
    Labels1[I] := TLabel.Create(GroupBox1);
    Labels1[I].Parent := GroupBox1;
    Labels1[I].Caption := Description[I];
    Edits1[I] := TSpinEdit.Create(GroupBox1);
    Edits1[I].Parent := GroupBox1;
  end;
end;
Erstellungsreihenfolge ist TLabel->TSpinEdit->TLabel->TSpinEdit..., trotzdem werden die Labels alle zuerst platziert.
Zuletzt geändert von Korkenkrone am Do 23. Sep 2010, 22:14, insgesamt 1-mal geändert.

pluto
Lazarusforum e. V.
Beiträge: 7192
Registriert: So 19. Nov 2006, 12:06
OS, Lazarus, FPC: Linux Mint 19.3
CPU-Target: AMD
Wohnort: Oldenburg(Oldenburg)

Re: Formular Grid-Layout

Beitrag von pluto »

Ich würde es einfach selbst versuchen. So Viel Aufwand ist das ja auch wieder nicht. Einfach zwei Forschleifen. Die eine geht die Y Werte durch, die andere die X Werte.
Daraus kannst du ein Raster Bilden. Wobei jede Komponente Gleichgroß sein sollte. Ist es das was du möchtest ?
Du kannst natürlich auch Spilter hinzufügen.

Wenn du das ganze noch in einer TScrollBox packst, kannst du sogar fast Problemlos Scrollen.
MFG
Michael Springwald

Korkenkrone
Beiträge: 33
Registriert: Sa 18. Sep 2010, 20:33
OS, Lazarus, FPC: OpenSUSE 11.3 (L 0.9.28.2 Beta FPC 2.2.4)
CPU-Target: x86-64

Re: Formular Grid-Layout

Beitrag von Korkenkrone »

Danke für die Antwort. Wie komme ich denn an die "Autosize"-Werte? Wenn ich die Controls im Raster verwalten möchte, muss ich die Height und Width Properties ja verändern. Autosize anschalten, Width Und Height auslesen und dann Autosize wieder abschalten um die Controls ins Raster einzupassen ist keine schöne Lösung.

pluto
Lazarusforum e. V.
Beiträge: 7192
Registriert: So 19. Nov 2006, 12:06
OS, Lazarus, FPC: Linux Mint 19.3
CPU-Target: AMD
Wohnort: Oldenburg(Oldenburg)

Re: Formular Grid-Layout

Beitrag von pluto »

Das Problem dabei ist: AutoSize hat nicht jede Komponente. Ich meine nur das Label, CheckBox und RadioButton z.b.

Du könntest dir auch ein Grid aus Panels aufbauen und dann jedem "Kasten" eine Komponente zuordnen und dann die Aligen Eigenschaft nutzen.

Kannst du mal ein Bild erstellen, wie das ganze mal aussehen könnte oder soll ?
MFG
Michael Springwald

Korkenkrone
Beiträge: 33
Registriert: Sa 18. Sep 2010, 20:33
OS, Lazarus, FPC: OpenSUSE 11.3 (L 0.9.28.2 Beta FPC 2.2.4)
CPU-Target: x86-64

Re: Formular Grid-Layout

Beitrag von Korkenkrone »

Wie es aussehen soll, macht vielleicht der Code deutlicher, den ich bisher für ein GridLayout geschrieben habe:
http://pastebin.com/40TLt2ba" onclick="window.open(this.href);return false;

Derzeit möchte ich es so machen, dass ich Anzahl der Zeilen und Anzahl der Spalten angeben kann und dann die Controls den einzelnen Feldern (Zeilennummer, Spaltennummer) zuwesien kann. Es soll für jede Zeile die Höhe der Zeile anhand der "Autosize"-Höhe des höchsten Controls in der Zeile bestimmt werden. Für jede Spalte soll die Breite anhand der Breite des breitesten Controls in der Zeile bestimmt werden. Aus Höhe und Breite wird dann für jede Zeile und Spalte jeweils Position und Maße berechnet und die Controls anhand Breite und Position der Spalte sowies Höhe und Position der Zeile platziert und skaliert werden.

Es ist also ein klassisches Tabellenlayout, wobei die Größe der Spalten jeweils genauso groß ist, dass alle Elemente hinein passen. Bei einem zweispaltigen Layout (Formular) ist also die erste Spalte so breit wie das breiteste Label, die zweite Spalte so breit wie das breiteste Edit-Feld.

Code: Alles auswählen

--------------------------
|Name         |Mustermann|
--------------------------
|Vorname      |Max       |
--------------------------
|Telefonnummer|0123456789|
--------------------------
Wenn sich hier jetzt "Vorname" zu "Vorname oder Spitzname oder Was auch immer" ändert, soll sich auch das Layout entsprechend anpassen.

pluto
Lazarusforum e. V.
Beiträge: 7192
Registriert: So 19. Nov 2006, 12:06
OS, Lazarus, FPC: Linux Mint 19.3
CPU-Target: AMD
Wohnort: Oldenburg(Oldenburg)

Re: Formular Grid-Layout

Beitrag von pluto »

Wie wäre es mit einer ListView ? Die kann sowas. der es gibt eine OI Komponente. Die kann auch sowas.

Welche Komponenten kommen denn zum Einsatz ? Bei den Meisten Komponenten musst du die Breite z.b. selbst ermitteln. Über Canvas.TextWidht z.b.

Geht es dir nur um eine Ausgabe ? Oder soll man die Ausgabe auch Bearbeiten können oder Markieren und der Gleichen ?
MFG
Michael Springwald

Korkenkrone
Beiträge: 33
Registriert: Sa 18. Sep 2010, 20:33
OS, Lazarus, FPC: OpenSUSE 11.3 (L 0.9.28.2 Beta FPC 2.2.4)
CPU-Target: x86-64

Re: Formular Grid-Layout

Beitrag von Korkenkrone »

Es sollen in der linken Spalte TLabels angezeigt werden, in der rechten Spalte brauche ich momentan TComboBox und TSpinEdit. Die rechte Spalte kann aber ruhig an den Parent rechts verankert werden, da brauche ich kein Autosize. Im Grunde genommen geht es also nur um TLabels für die ich die Autosize-Werte brauche. Es wäre natürlich schön, wenn ich eine wiederverwendbare Layoutunit, wie ich sie ja schon provisorisch angefangen habe, verwenden könnte.

Ich kann mich mal in Listview einlesen, oder dieser Komponente. Vielleicht geht das ja.

pluto
Lazarusforum e. V.
Beiträge: 7192
Registriert: So 19. Nov 2006, 12:06
OS, Lazarus, FPC: Linux Mint 19.3
CPU-Target: AMD
Wohnort: Oldenburg(Oldenburg)

Re: Formular Grid-Layout

Beitrag von pluto »

Die Werte für die Breite werden Normalerweise Automatisch gesetzt, wenn AutoSize True ist. Also kannst du sie einfach abfangen.
Du brauchst nur eine Funktion schreiben, die dir von einer Spalte die breiteste Breite Liefert. Damit kannst du dann weiter machen.
Im Prinzip ist das, eine OI Komponente. Diese musst du jedoch erst Installieren.

Ist jedoch bei Lazarus Dabei. Die IDE nutzt diese Komponente sogar. Wenn du die OI Komponente nutzt, brauchst du dir nur Klassen zu erstellen.
Diese Klassen müssen dann im published Bereich die Eigenschaften haben.

Wenn du gar nicht weiter kommst, könnte ich auch ein kleines Beispiel erstellen, jedoch nur als allerletzte Möglichkeit.
MFG
Michael Springwald

Korkenkrone
Beiträge: 33
Registriert: Sa 18. Sep 2010, 20:33
OS, Lazarus, FPC: OpenSUSE 11.3 (L 0.9.28.2 Beta FPC 2.2.4)
CPU-Target: x86-64

Re: Formular Grid-Layout

Beitrag von Korkenkrone »

Ich will ja den Umgang mit FreePascal und Lazarus lernen, da ist es ganz gut, wenn ich mir ein bischen die Zähne ausbeiße. Also mach dir bitte keine zusätzliche Mühe mit Code vorschreiben. :)

Ich habe meinen Layouter etwas vereinfacht, da das was ich vor hatte keinen großen Sinn macht, wenn nicht jedes Control einen Autosize Wert hat. Statt dem allgemeinen Grid-Layout habe ich jetzt nur noch ein recht schlankes (aber durchaus erweiterbares) Formlayout, das nur die Edit Spalte aufnimmt und die zugehörigen Labels selbst erstellt. Wie kann ich denn das Autosize abfangen? Lasse ich die Label auf Autosize und greife die Width und Height Properties ab, bekomme ich scheinbar nicht die Autosize Werte.

Code: Alles auswählen

unit FormLayout;
 
{$mode objfpc}{$H+}
 
interface
 
uses
  Classes, SysUtils, StdCtrls, Controls;
type
  TRow = record
    Height: Integer;
    Caption: TLabel;
    Item: TControl;
  end;
 
  TFormLayout = class(TObject)
  private
    FRows: array of TRow;
    FLabelWidth: Integer;
  public
    Append(Item:TControl; Caption: String);
    ReLayout;
  end;
 
implementation
  procedure TFormLayout.Append(Item: TControl; Caption: String);
  begin
    SetLength(FRows, Length(FRows) + 1);
 
    FRows[Length(FRows)-1].Item := Item;
    FRows[Length(FRows)-1].Caption := TLabel.Create(Item.Parent);
    FRows[Length(FRows)-1].Caption.Caption := Caption;
    FRows[Length(FRows)-1].Caption.Parent := Item.Parent;
 
    { Adjust the Row and/or Columm sizes, if they are
      too small to store the new item }
    if FRows[Length(FRows)-1].Caption.Width > FLabelWidth then
      FLabelWidth := FRows[Length(FRows)-1].Caption.Width;
    if FRows[Length(FRows)-1].Caption.Height > Item.Height then
      FRows[Length(FRows)-1].Height := FRows[Length(FRows)-1].Caption.Height
    else
      FRows[Length(FRows)-1].Height := Item.Height;
  end;
 
  procedure TFormLayout.ReLayout;
  var
    VertPosition: Integer;
    Line: Integer;
  begin
    VertPosition := 0;
    For Line := 0 to Length(FRows)-1 do begin
      FRows[Line].Caption.Top := VertPosition;
      FRows[Line].Caption.Left := 0;
      FRows[Line].Item.Top := VertPosition;
      FRows[Line].Item.Left := FLabelWidth + 1;
 
      Inc(VertPosition, FRows[Line].Height);
    end;
  end;
end.
Es fehlen natürlich noch einige Dinge, wie eine Zentrierung der Labels (oder der Controls, falls diese kleiner sind) in ihrer Zeile, Zugriff auf Caption und Design der Labels, optionales Ankern der Controls an die rechte Innenseite des Parents, typische Funktionen für Listen und Arrays wie insert und remove, oder einstellbarer Abstand zum Parent sowie zwischen Zeilen und Spalten.

Vielen Dank für die Mühe, die du dir gibst.

Was ist eine OI Komponente? Ist das die, die im ObjectInspector eingesetzt wird? Dann kann ich da mal in den Source schauen. Schön finde ich die (in der Einstellung wie in der IDE) allerdings für meine Zwecke nicht, da Teile der Controls, wie der "Listenknopf" der ComboBox, scheinbar erst sichtbar werden, wenn man das Feld anwählt.

pluto
Lazarusforum e. V.
Beiträge: 7192
Registriert: So 19. Nov 2006, 12:06
OS, Lazarus, FPC: Linux Mint 19.3
CPU-Target: AMD
Wohnort: Oldenburg(Oldenburg)

Re: Formular Grid-Layout

Beitrag von pluto »

Was ist eine OI Komponente? Ist das die, die im ObjectInspector eingesetzt wird?
Ja genau.
Dann kann ich da mal in den Source schauen.
So einfach wird das auch nicht. Der ist recht Umfangreich. Aber ein Versuch ist es Wert.
Zwecke nicht, da Teile der Controls, wie der "Listenknopf" der ComboBox, scheinbar erst sichtbar werden, wenn man das Feld anwählt.
Das ist bei einem OI durchaus gewollt.

Du kannst natürlich auch jede andere Eingabe Komponente Anpassen.
Die Linke Seite soll doch nur aus Labels bestehen ? Also brauchst du hier nur eine Funktion, die Ausfindig macht, welches Label das breitest ist. Hier kannst du die AutoSize Funktion nutzen. D.H. Du musst alle Labels zu erst erstellen. Du kannst sie auch nacheinander erstellen. Nur dann musst du mit Canvas.TextWidht die Breite Ermitteln. Das Label hat den Vorteil: Es Unterstützt nur eine Schrift Formatierung. Also kannst du die Werte die unter der Font Eigenschaft stehen 1:1 in ein Canvas.Font übertragen. Bei diesem Vorgehen musst du jedoch ebenfalls zunächst das breiteste Label ermitteln.

Also spielt es keine Rolle wie du vorgehst.

Du brauchst sogar keine eigene Liste. Die LCL Führt bereist eine mit. Wenn du den erstellen Komponenten Namen zuweist kannst du mit FindComponent Arbeiten. Nicht mal das ist Notwendig.
Da ja Alle Komponenten auf der Rechten Seite Ähnliche Eigenschaften haben, könntest du hier auch mit dem Sender Parameter Arbeiten.

Bei der Zweiten Spalte spielt die Breite der jeweiligen Komponente ja keine Große Rolle. Sondern nur die Höhe. Diese muss natürlich mit der ersten Spalte zusammen Passen. Eine ComboBox braucht nun mal mehr Platz als ein label oder ein Edit.

Ich hoffe damit kommst du erstmal weiter. Du könntest sogar eine Spilter Komponente einsetzten. Um die Breite der jeweiligen Spalte vom User bestimmbar zu machen. Wie es im OI der Fall ist.

Wie du siehst gibt es mehrere Möglichkeiten. Welche die Sinnvollste ist kannst nur du Entscheiden.
MFG
Michael Springwald

Korkenkrone
Beiträge: 33
Registriert: Sa 18. Sep 2010, 20:33
OS, Lazarus, FPC: OpenSUSE 11.3 (L 0.9.28.2 Beta FPC 2.2.4)
CPU-Target: x86-64

Re: Formular Grid-Layout

Beitrag von Korkenkrone »

So, noch einmal vielen Dank für deine Hilfe. Ich habe mein Design der Form-Layout-Klasse noch einmal erweitert und verbessert und es funktioniert jetzt dank TCanvas.TextHeight und TCanvas.TextWidth einwandfrei:
http://pastebin.com/hF2LLBe5" onclick="window.open(this.href);return false;

Natürlich fehlen noch ein paar Funktionen, aber die füge ich dann hinzu, wenn ich sie brauche. Ich muss ganz ehrlich sagen, dass ich in der Hinsicht ein bischen enttäuscht bin. Bisher war die LCL in meinen Augen immer fast einwandfrei, aber dass man mit 3 Konzepten für dynamisches Layout (ChildSizing, Align, Anchors) kein Form-Layout bekommen kann, finde ich nicht schön. Ich musste bisher nie eigenen Code zum manuellen Layouten erstellen (Qt, GTK) und ein klassisches Formular ist nichts wirklich exotisches. Ansonsten bin ich weiterhin von FreePascal/Lazarus begeistert.

Bora4d
Beiträge: 290
Registriert: Mo 24. Dez 2007, 13:14
OS, Lazarus, FPC: WinXP-Pro-Sp3, Xubuntu 12.04, (Laz 1.1-SVN Mai2012, FPC 2.6.1 / 2.6.0-Linux)
CPU-Target: AMD64X2

Re: [gelöst] Formular Grid-Layout

Beitrag von Bora4d »

@Korkenkrone:
Wenn du schon so weit gemacht hast. Kannst du doch deine Komponente gleich von TGraphicControl ableiten und TRow von TCollectionItem und FRows von TOwnedCollection dann hast du eine Komponente die du im Formulardesigner immer verwenden kannst. Dann brauchst du auch nicht TLabel kannst gleich selber zeichnen.
Und bei TRow kannst du ItemTyp (Edit,Listbox,...) einführen dann kann dein Komponente sogar die Controls automatisch erstellen.
Dank dir hab ich jetzt eine gute idee für'n tolle Komponente :lol: Früher habe für sowas immer StringGrid mißbraucht. :D

pluto
Lazarusforum e. V.
Beiträge: 7192
Registriert: So 19. Nov 2006, 12:06
OS, Lazarus, FPC: Linux Mint 19.3
CPU-Target: AMD
Wohnort: Oldenburg(Oldenburg)

Re: [gelöst] Formular Grid-Layout

Beitrag von pluto »

@Korkenkrone
Du kannst den Code auch direkt hier Posten. Wenn du ein Beitrag schreibst, siehst du doch unter anderem eine ComboBox. Wo Highligter drauf steht.
Da einmal drauf klicken und den Richtigen auswählen.

@Bora4d
Warum von TGraphicControl ableiten und nicht direkt von TCustomControl ? Hat das TGraphicControl Vorteile gegenüber TCustomControl ?
Die Idee ist sehr verlockend. Im Prinzip könnte ich meine eigene ListView, die ich mal erstellt habe dafür verwenden *G*.... mit einigen kleineren Änderungen.

Viel Spaß bei der Entwickelung.
MFG
Michael Springwald

Bora4d
Beiträge: 290
Registriert: Mo 24. Dez 2007, 13:14
OS, Lazarus, FPC: WinXP-Pro-Sp3, Xubuntu 12.04, (Laz 1.1-SVN Mai2012, FPC 2.6.1 / 2.6.0-Linux)
CPU-Target: AMD64X2

Re: [gelöst] Formular Grid-Layout

Beitrag von Bora4d »

pluto hat geschrieben: @Bora4d
Warum von TGraphicControl ableiten und nicht direkt von TCustomControl ? Hat das TGraphicControl Vorteile gegenüber TCustomControl ?
Die Idee ist sehr verlockend. Im Prinzip könnte ich meine eigene ListView, die ich mal erstellt habe dafür verwenden *G*.... mit einigen kleineren Änderungen.

Viel Spaß bei der Entwickelung.
Ich bin schon fertig (99%) :D . Sieht verdammt gut aus. Warum habe ich das nicht schon früher gemacht. :roll:
Sehr flexibel geworden, man kann sogar caption und controller bereich verbinden um z.b. Memos zu plazieren und einzelne Zeilen ausblenden. Labels und Bevels werden automatisch gezeichnet und Zeilen kann man als Abschnittstitel verwenden.
Eingabute Splitter kommt noch dazu dann kann ich die Align-Eigenschaften von Komponenten, Panele und Splitters vergessen.
Mann kann sein Formular wie Html-Tabelle gestalten.

Warum Graphiccontrol?
1. Bin dran gewohnt früher(Win3.1/95) waren Fenster-Handles mangelware und die sollen schneller gezeichnet werden weil Kommunikation mit System nicht stattfindet. Geschwindigket habe ich nicht getestet ich vertraue den alten Borland-Jungs.
2. Flexible, mann kann bei den Transparenz sehr einfach verwenden. Wenn du sie nicht zeichnest sind die schon Transparent. :D
3. Wenn ich Fenster brauche plaziere ich es einfach in Panel oder Scrollingwindow.

Auch dir wünsche ich viel Spaß

Korkenkrone
Beiträge: 33
Registriert: Sa 18. Sep 2010, 20:33
OS, Lazarus, FPC: OpenSUSE 11.3 (L 0.9.28.2 Beta FPC 2.2.4)
CPU-Target: x86-64

Re: [gelöst] Formular Grid-Layout

Beitrag von Korkenkrone »

Bora4d hat geschrieben:@Korkenkrone:
Wenn du schon so weit gemacht hast. Kannst du doch deine Komponente gleich von TGraphicControl ableiten und TRow von TCollectionItem und FRows von TOwnedCollection dann hast du eine Komponente die du im Formulardesigner immer verwenden kannst. Dann brauchst du auch nicht TLabel kannst gleich selber zeichnen.
Und bei TRow kannst du ItemTyp (Edit,Listbox,...) einführen dann kann dein Komponente sogar die Controls automatisch erstellen.
Dank dir hab ich jetzt eine gute idee für'n tolle Komponente :lol: Früher habe für sowas immer StringGrid mißbraucht. :D
Ich kann mal schauen. Im Grunde ist ja ein array, ein record und TObject leichtgewichtiger als die von dir genannten möglichen Typen, also brauche ich da schon gute Gründe auf diese zurück zu greifen. Eine in der IDE dargestellte Komponente wäre natürlich schön, aber dafür langt ja TComponent anstatt TObject aus. Der Vorteil wäre dann, dass ich beim Zuordnen der Controls an den Layouter gleich Parent und Owner der Controls anpassen könnte, da der Layouter selbst Parent und Owner kennt.

Diese Ansicht könnte aber natürlich auch daher kommen, dass ich mich in der LCL einfach überhaupt noch nicht auskenne.

pluto hat geschrieben:Du kannst den Code auch direkt hier Posten. Wenn du ein Beitrag schreibst, siehst du doch unter anderem eine ComboBox. Wo Highligter drauf steht.
Da einmal drauf klicken und den Richtigen auswählen.
Ja, habe ich ja oben auch gemacht. Ab einer gewissen Größe des Quelltextes stört das aber meiner Meinung nach die Übersicht und der letzte Paste hatte immerhin 143 Zeilen.

Antworten