Gehirnakrobatik rund um TPageControl

Rund um die LCL und andere Komponenten
charlytango
Beiträge: 1080
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: Gehirnakrobatik rund um TPageControl

Beitrag von charlytango »

wp_xyz hat geschrieben: Do 5. Jun 2025, 11:50 Ganz schön geschickt gemacht, das ganze...
Ja, das merke ich schon -- und ich merke auch dass mir das noch eine Weile Kopfschmerzen bereiten wird ;-) (und damit wohl auch dir gggg)

charlytango
Beiträge: 1080
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: Gehirnakrobatik rund um TPageControl

Beitrag von charlytango »

Bericht:
Tabs und die dazu gehörenden Seiten lassen sich nun sauber einfügen und auch wieder löschen.
Der Check ob gelöscht/geschlossen werden darf klappt gut. Auch feststehende Tabs auf der linken Seite sind ok.

Wenn die Anzahl der Tabs zu viel für den Anzeigebereich wird, werden Navigationspfeile angezeigt, was gut ist. Leider sind die auf meinem hochauflösenden Monitor winzig

Dier nächste anstehende Aufgabe wäre, so etwas wie einen Button mit einem Plus und einen Button mit einem Pfeil einzubauen. Plus würde eine neue Seite erzeugen und der Pfeil ein Menü für die bestehenden aufmachen.

Meine Versuche auf dem JvTabBar einen Button direkt zu verankern blieben erfolglos.
Mit den alten Tricks, Panels einzusetzen bekommt man das schon hin, aber geht das eleganter ?

Edit: Das geht eleganter. Langsam setzt sich der Anker-Editor durch.
Dateianhänge
Screenshot 2025-06-05 132814.png
Screenshot 2025-06-05 132814.png (10.59 KiB) 1063 mal betrachtet
Screenshot 2025-06-05 130501.png
Screenshot 2025-06-05 130501.png (5.94 KiB) 1063 mal betrachtet

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

Re: Gehirnakrobatik rund um TPageControl

Beitrag von wp_xyz »

charlytango hat geschrieben: Do 5. Jun 2025, 13:38 Wenn die Anzahl der Tabs zu viel für den Anzeigebereich wird, werden Navigationspfeile angezeigt, was gut ist. Leider sind die auf meinem hochauflösenden Monitor winzig
Die sind mir tatsächlich damals durch die Lappen gegangen, und ihre Größe steht noch als Konstante im Quelltext. Ist nun in der SVN-Version behoben. Allerdings gefällt mir das noch nicht, weil der Bereich mit den Scrollbuttons in gesamter Höhe übermalt wird, so dass das äußerste rechte Tab abgeschnitten wird, sobald er zu nahe kommt. Außerdem hat Windows 11 so bescheuerte Themes, dass der klickbare Scrollbutton ausgeblendet wird (es handelt sich anscheinend um die Scrollbar-Arrow-Themes), und wenn man nur den inaktiven ScrollButton sieht, ist das extrem verwirrend.

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

Re: Gehirnakrobatik rund um TPageControl

Beitrag von wp_xyz »

Ich habe die TJvTabBar nun etwas überarbeitet: bessere Darstellung der Scroll-Buttons, ein paar neue Properties.
Dateianhänge
JvTabBarDemo.png
JvTabBarDemo.png (29.68 KiB) 967 mal betrachtet

charlytango
Beiträge: 1080
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: Gehirnakrobatik rund um TPageControl

Beitrag von charlytango »

Oh -- danke sehr !!

Darf ich etwas unverschämt sein und mir noch zwei/drei Buttons rechts wünschen? 8)

- einen Button um ein Tab hinzuzufügen
- einen zweiten um Tabs als Liste anzuzeigen
- einen dritten um Tabs rechts außen löschen zu können.

Im wesentlichen müsste da keine Funktion hinter den Buttons stehen sondern nur zum ein/ausschalten und eine Eventprozedur die man von außen befüllen kann.
Oder es fällt dir noch etwas besseres ein wie man so etwas dynamisch lösen kann.

Vor allem optisch sind die Browser da voraus - vielleicht hat da auch jemand einen Tip oder Trick der die Optik verbessert. Windows Buttons sind halt nicht mehr der letzte Schrei.
Runde Ecken der Tab wären ein erster Schritt ;-)

Ich will nicht nerven -- das Teil ist jetzt schon besser

Benutzeravatar
af0815
Lazarusforum e. V.
Beiträge: 6845
Registriert: So 7. Jan 2007, 10:20
OS, Lazarus, FPC: FPC fixes Lazarus fixes per fpcupdeluxe (win,linux,raspi)
CPU-Target: 32Bit (64Bit)
Wohnort: Burgenland
Kontaktdaten:

Re: Gehirnakrobatik rund um TPageControl

Beitrag von af0815 »

charlytango hat geschrieben: Sa 7. Jun 2025, 09:46 Darf ich etwas unverschämt sein und mir noch zwei/drei Buttons rechts wünschen? 8)

- einen Button um ein Tab hinzuzufügen
- einen zweiten um Tabs als Liste anzuzeigen
- einen dritten um Tabs rechts außen löschen zu können.
Das sind aber im wesentlichen Funktionen, die auch bei Browsern auf dem Kontextmenü liegen und dazu keine direkten Buttons vorhanden sind (ausser einem + für Tab hinzufügen vielleicht).
charlytango hat geschrieben: Sa 7. Jun 2025, 09:46 Vor allem optisch sind die Browser da voraus - vielleicht hat da auch jemand einen Tip oder Trick der die Optik verbessert. Windows Buttons sind halt nicht mehr der letzte Schrei.
Runde Ecken der Tab wären ein erster Schritt ;-)
Ein Diskussion welche Form die Tabs haben sollen ist Geschmack und ändert sich von BS zu BS, von Widgetset zu Widgetset, bzw. was der Benutzer für ein Theme konfiguriert hat. Wenn jetzt MS oder Apple eine geistige Blähung hat und die Echen müssen wieder scharf sein, hat man genau den anderen Wunsch.

Dank an WP für die umgesetzten Ideen.
Blöd kann man ruhig sein, nur zu Helfen muss man sich wissen (oder nachsehen in LazInfos/LazSnippets).

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

Re: Gehirnakrobatik rund um TPageControl

Beitrag von wp_xyz »

Jetzt auch mit abgerundeten Tabs. Und - falls es so kommt wie bei den Autos, dass nämlich nach den knuddeligen runden Karosserien die Bügelfalten-Karosserien kommen - gibt es sie auch in einer abgeschnittenen Version (Property TabShape = (tsRectangular, tsRounded, tsCut) ).

Das mit den Zusatzbuttons ist ein gewisses Problem, nämlich weil die ursprünglichen Entwickler der Komponente Buttons im Code nachahmen, anstatt, wie ich es getan hätte, einfach SpeedButtons zu integrieren, kann man viele Vorteile der LCL nicht nützen, und muss sich um viele Details kümmern.
Dateianhänge
JvTabBarDemo-rounded.png
JvTabBarDemo-rounded.png (36.38 KiB) 813 mal betrachtet

kirchfritz
Beiträge: 227
Registriert: Mo 3. Jan 2011, 13:34
OS, Lazarus, FPC: Win11 (L 3.0 FPC 3.2.2)
CPU-Target: 64Bit
Wohnort: Nürnberg

Re: Gehirnakrobatik rund um TPageControl

Beitrag von kirchfritz »

Hallo wp_xyz,

wo findet man die überarbeitete TJVTabBar-Komponente?

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

Re: Gehirnakrobatik rund um TPageControl

Beitrag von wp_xyz »

Das ist im CCR-Repository auf Sourceforge. Es gibt folgende Möglichkeiten, das Update zu bekommen:

charlytango
Beiträge: 1080
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: Gehirnakrobatik rund um TPageControl

Beitrag von charlytango »

Also, nach einigem rumtesten hier nochmal die Grundidee:

ich möchte das Duo JvTabBar und JvPageList dazu verwenden eine tabbed Benutzeroberfläche zu schaffen.
Es soll so funktionieren dass in die Tabs/TPagelist einzelne zur Laufzeit erstellte Formulare eingehängt und geschlossen werden können.
Die eingehängten Formulare haben einen gemeinsamen Vorfahren der all diese UI Funktionalitäten übernimmt und die abgeleiteten Formulare quasi ganz normale Formulare sind (bis auf den anderen Vorfahren).
Die Formulare sollen auch "ausgehängt" werden können, dh sie sind dann zwar mit der Owner-Eigenschaft noch mit dem Hauptformular verbunden, aber haben dann keinen Parent mehr. Sie sind also quasi "frei fliegend". (Zweck: zb ein Formular neben die eingedockten zu stellen um zb Vergleiche durchzuführen)
Die Tabs sollen auch eine einstellbare Anzahl "fixer" Tabs von links haben, die nicht geschlossen werden können (zb permanent verfügbare Suchfenster)

meine aktuellen Stolpersteine:
1)
ich kann das entworfene Vorfahrenformular (TFormParentPage) jetzt auf zwei Arten erstellen und einhängen. Die wohl konservative Methode wie auch die anderen Formulare im Beispiel erstellt wurden oder die Methode in der dem Partntformular JvTabBar und JvPageList zugewiesen werden und eine prozedur im Parentformular erledigt das Einklinken. Passt soweit.
Auch das Ausklinken mit einem Button auf dem Formular klappt.
Was dzt noch gar nicht klappt ist das wieder einbauen einer ausgeklinkten Form in die Tabs obwohl ich dazu die gleiche Funktion verwende wie beim ersten Einklinken. In Zeile 117 kommt es zu einer Exception. Keine Ahnung warum -- Bitte Hilfe

2) [Der Tip mit dem Pointer klappt grundsätzlich - ob das dann real ausreicht wird sich zeigen]
Für das Ausklinken vom Hauptformular aus braucht es noch eine Möglichkeit auf die jeweils eingeklinkte Form zuzugreifen ohne zu wissen welche das denn ist. Ich werde mal versuchen die Components einer Page durchzusteppen. Eigentlich dürfte da dann ja nur eine drauf sein.

3) [das klappt trotz published Anchor nicht so richtig]
Ich versuche auch den JvTabBar im Hauptformular mit Ankern zu fixieren -- bisher hat er sich allen Versuchen entzogen.
Die Idee war, neben dem TabBar ein Panel mit Speedbuttons zu verankern was bisher fehlschlug.

4)
Auch habe ich Probleme mit der Höhe des TabBar bei Monitoren verschiedener Auflösung.

5)
Im Verhältnis zur Schrift sind die Icons optisch etwas groß.

6)
Die fixierten Tabs funktionieren wenn man sich auf das Schließen beschränkt.
Wenn man Tabs verschieben darf hab ich noch keine Lösung dafür.

7) [Erledigt]
Die Events im JvTabBar klingen mir etwas kryptisch: bei OnTabClosed würde ich erwarten dass das feuert wenn ein Tab geschlossen wurde.
Scheinbar existiert der Tab zu dem Zeitpunkt noch, denn ein Refresh für eine Liste existierender Tabs fürs Menü zeigt ihn noch an.
Kein Beinbruch, aber scheinbar denke ich falsch

THX
Dateianhänge
JvTabBarDemo_PageList.zip
(41.77 KiB) 45-mal heruntergeladen
Zuletzt geändert von charlytango am Mi 11. Jun 2025, 17:13, insgesamt 2-mal geändert.

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

Re: Gehirnakrobatik rund um TPageControl

Beitrag von wp_xyz »

charlytango hat geschrieben: Mi 11. Jun 2025, 12:57 Ich versuche auch den JvTabBar im Hauptformular mit Ankern zu fixieren -- bisher hat er sich allen Versuchen entzogen.
Die Idee war, neben dem TabBar ein Panel mit Speedbuttons zu verankern was bisher fehlschlug.
Hab gerade gesehen, dass die Anchors-Eigenschaft nicht veröffentlicht war. Hole dir die aktuelle svn-Version, oder füge in deiner Version ein "property Anchors;" im Published-Abschnitt von TJvTabBar hinzu
Auch habe ich Probleme mit der Höhe des TabBar bei Monitoren verschiedener Auflösung.
Kann ich mangels Monitoren (oder eigentlich: Schreibtischplatz) nicht prüfen. Hast du in den Projekt-Einstellungen die richtige scaling-Option eingestellt? (unter "Use manifest resource" eine der "per-monitor"-Optionen)
Im Verhältnis zur Schrift sind die Icons optisch etwas groß.
Du kannst natürlich deine eigenen Icons nehmen. In dem Demo-Programm sind sie halt 24x24 px. Nimm 16x16 stattdessen. Im Images/General_purpose-Ordner der Lazarus-Installation findest du "alle" Größen
Die Events im JvTabBar klingen mir etwas kryptisch: bei OnTabClosed würde ich erwarten dass das feuert wenn ein Tab geschlossen wurde.
Scheinbar existiert der Tab zu dem Zeitpunkt noch, denn ein Refresh für eine Liste existierender Tabs fürs Menü zeigt ihn noch an.
Das Problem ist aber, dass der "geschlossene" Tab als Parameter an das Event mitgegeben worden ist. Wenn der Tab aber wirklich schon geschlossen ist, dann gibt es den Parameter auch nicht. Blöde Konstruktion - ich hätte den Parameter weggelassen. Ich will das aber auch nicht ändern, weil es ein Property ClosingTab gibt, der an mehreren Stellen verwendet wird, und da mache ich mit Sicherheit etwas kaputt. Du darfst halt beim erneuten Einlesen des Menüs nur die tabs aufnehmen, die nicht dem Tab-Parameter des Events, also dem ClosingTab, entsprechen.

Code: Alles auswählen

procedure TMainForm.RenewMenuItems(mCon: TMenuItem);
begin
  [...]
  for i:=0 to jvtabbar1.Tabs.Count  -1 do
  begin
    if jvTabBar1.tabs[i] = JvTabBar1.ClosingTab then
      Continue;
    MyItem:=TMenuItem.Create(mCon);
    [...]
end;
charlytango hat geschrieben: Mi 11. Jun 2025, 12:57 ich kann das entworfene Vorfahrenformular (TFormParentPage) jetzt auf zwei Arten erstellen und einhängen. Die wohl konservative Methode wie auch die anderen Formulare im Beispiel erstellt wurden oder die Methode in der dem Partntformular JvTabBar und JvPageList zugewiesen werden und eine prozedur im Parentformular erledigt das Einklinken. Passt soweit.
Auch das Ausklinken mit einem Button auf dem Formular klappt.
Was dzt noch gar nicht klappt ist das wieder einbauen einer ausgeklinkten Form in die Tabs obwohl ich dazu die gleiche Funktion verwende wie beim ersten Einklinken. In Zeile 117 kommt es zu einer Exception. Keine Ahnung warum -- Bitte Hilfe
aForm ist eine lokale Variable in der Einlinken-Prozedur und wurde nirgendwo erzeugt. Daher gibt es auch kein Property Parent.
charlytango hat geschrieben: Mi 11. Jun 2025, 12:57 Für das Ausklinken vom Hauptformular aus braucht es noch eine Möglichkeit auf die jeweils eingeklinkte Form zuzugreifen ohne zu wissen welche das denn ist. Ich werde mal versuchen die Components einer Page durchzusteppen. Eigentlich dürfte da dann ja nur eine drauf sein.
Eine Page der PageList müsste eigentlich ein Tag-Property haben. Da kannst du den Zeiger auf das Formular ablegen, und du weißt immer, welches Formular sich auf dem aktuellen Tab befindet.

charlytango
Beiträge: 1080
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: Gehirnakrobatik rund um TPageControl

Beitrag von charlytango »

ich habe in der usprünglichen Liste zu den Punkten Bemerkungen dazu editiert.

Das mit dem Anker funktioniert besser aber noch nciht optimal.

LCL-Scaling -- checked
Use manifest resource -- checked
DPI awareness -- on(True)

aber lassen wird sie Auflösung mal beiseite, das gehen wir danach an

Die Menüstrukturierung im OnTabClosed hat mit deinem Tip geklappt - passt erstmal, Finetunig später

Dem Tag-Property der jeweiligen Page konnte ich einen Zeiger der eingeklinkten Seite zuordnen und mit einem Menüpunkt von außerhalb die Caption auslesen -- Schritt eins mal grundsätzlich geschafft.

Was sich noch heftig wehrt ist das Einklinken und Ausklinken eines Formulars mittels eines Vorgängerformulars.
Das Ausklinken klappt.
Das erstmalige Einklinken klappt auch.
Nachdem ich die Prozedur angepasst habe klappt auch das wieder-Einklinken, hat aber unerwartete Side-Effects.
In Zeile 96 wird ohne ersichtlichen Grund nun aus dem MainForm die Prozedur AddMultipleTabs angesprungen und ausgeführt. Mit dem Ergebnis dass eben 4 zusätzliche Tabs eingehängt werden

Code: Alles auswählen

procedure TFormParentPage.Einklinken;
var
  aTab:TJvTabBarItem;
  iPageNumber:integer;
begin
  if assigned(Self) then begin
    {offensichtlich wird auch gleichzeitig eine jvStandardpage
     in der Pagelist angelegt und synchronisiert.}
    aTab:=FTabBar.AddTab(FsCaption);

    aTab.ImageIndex:=FImageIndex;
    FTabBar.SelectedTab:=aTab;

    iPageNumber:=FTabBar.Tabs.Count-1;
    Self.Parent:=TJvPageList(FTabBar.PageList).Pages[iPageNumber];     //  <<--  aus unerfindlichem Grund wird in AddMultipleTabs gesprungen

    //Pointer des erzeugten Formulars in der Page der Pagelist hinterlegen
    TJvPageList(FTabBar.PageList).Pages[iPageNumber].Tag:=PtrInt(Self);

    Self.BorderStyle:=bsNone;
    Self.Align:=alclient;

    Self.Label1.Caption:=FsCaption;
    Self.Show;
 end
 else
  showmessage('Form unassigned');

end; 
Ist mir völlig schleierhaft warum -- grübel.
Auch ein Durchsteppen mit F8/F7 brachte keine Erkenntnisse
Dateianhänge
JvTabBarDemo_PageList.zip
(42.58 KiB) 67-mal heruntergeladen

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

Re: Gehirnakrobatik rund um TPageControl

Beitrag von wp_xyz »

charlytango hat geschrieben: Mi 11. Jun 2025, 20:50 Das mit dem Anker funktioniert besser aber noch nciht optimal.
Du hast das "Enabled"-Häkchen für den rechten Anker der TabBar nicht gesetzt - siehe Screenshot. Und PageList darfst du oben nicht mit dem Formular verankern, sondern mit dem unteren Rand der TabBar (also: im Feld "Top anchoring" "MainForm" durch JvTabBar1 ersetzen und in der Buttongruppe den unteren Butten klicken, außerdem das obere Borderspacing auf 0 oder etwas ähnliches)
charlytango hat geschrieben: Mi 11. Jun 2025, 20:50 In Zeile 96 wird ohne ersichtlichen Grund nun aus dem MainForm die Prozedur AddMultipleTabs angesprungen und ausgeführt. Mit dem Ergebnis dass eben 4 zusätzliche Tabs eingehängt werden
Das liegt daran, dass nach dem "Aushängen" offenbar das Hauptformular deaktiviert und nach dem "Einhängen" wieder aktiviert wird. Aber im OnActivate-Handler hast du den Aufruf von AddMultipleTabs... Entweder setze in OnActivate eine Status-Variable, die nach dem ersten Aufruf von OnActivate alle weiteren Aufrufe von AddMultipleTabs blockiert, oder packe das ganze Zeug einfach in OnCreate - ich sehe keinen Grund, warum das dort nicht stehen kann.

Übrigens, du kannst dir die ewigen Type-Casts von JvPageList sparen, indem du zusätzlich zu FTabBar eine PageList-Variable deklarierst, die halt schon den richtigen Typ hat. Du hast damit schon angefangen, es aber nicht bis zum Ende durchgezogen. Ungetestet:

Code: Alles auswählen

type
  TFormParentPage = class(TForm)
  ...
  private
    FTabBar: TJvTabBar;
    FPageList: TJvPageList;
    procedure SetTabBar(...);
    ...
  end;
  
  procedure TFormParentPage.SetTabBar(AValue: TJvTabBar);  // TFormParentPage.SetPageList kann mMn entfallen
  begin
    if FTabBar = AValue then exit;
    FTabBar := AValue;
    FPageList := TJvPageList(FTabBar.PageList);
  end;
  
procedure TFormParentPage.Einklinken;
var
  aTab:TJvTabBarItem;
  iPageNumber:integer;
begin
  if assigned(Self) then begin
    ...
    Self.Parent:=FPageList.Pages[iPageNumber];  
    FPageList.Pages[iPageNumber].Tag:=PtrInt(Self);
 
Du musst allerdings noch die Notification-Methode überschreiben, um FPageList auf nil zu setzen, wenn FTabs vom TFormParentPage gelöst, also nil wird. Denn FPageList leitet sich ja von FTabs ab, und wenn es FTabs nicht mehr gibt, dann gibt es FPagelist auch nicht mehr:

Code: Alles auswählen

    procedure TFormParentPage.Notification(Component: TComponent; Operation: TOperation); // in protected, und "override";
 begin
   inherited;
  if Operation = opRemove then
  begin
    if Component = FTabBar then
      FPageList := nil;
  end;
end;
Dateianhänge
jvtabbar-anchors.png
jvtabbar-anchors.png (25.86 KiB) 248 mal betrachtet

charlytango
Beiträge: 1080
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: Gehirnakrobatik rund um TPageControl

Beitrag von charlytango »

danke erstmal, ist einiges an Stoff zu verdauen.
Wollte mich nur mal bedanken und avisieren dass es ein, zwei Tage dauern könnte dass ich mich drum kümmern kann.

Antworten