ctGUI (Tabbed GUI auf Basis JvTabBar)

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

ctGUI (Tabbed GUI auf Basis JvTabBar)

Beitrag von charlytango »

Der GUI Vorschlag ctGUI ist zumindestens schon soweit gediehen dass man in einem Beispiel sehen kann wie es funktionieren kann. Ich habe einen neuen Thread geöffnet, der Beginn des Dramas ist hier nachzulesen

Mittlerweile funktionieren auch die Tabmenüs. Wo ich gar nicht weiterkomme ist bei ctGUI_frame.pas line 226.

Code: Alles auswählen

        if assigned(aForm) then begin
          aForm.Free;      //<-- hier      
        end
        else
          raise Exception.Create('aForm is not assigned -- that should never happen'); 
Dort soll ein "embedded" Formular zerstört werden. Funktioniert perfekt wenn man das X vom Tab benutzt oder eine Menüfunktion. Wenn man allerdings "aus dem Formular heraus" die (aus meiner Sicht gleiche) Funktion aufruft (die Formulare mit dem grünen Hintergrund und dem Close Button), kommt es zu einer ACCESS VIOLATION die mich ins Assembler Fenster schickt.
Das aber nur mit Debugger und Lazlogger. Die blanke Exe macht augenscheinlich was sie soll.
Der Zustand ist allerdings unhaltbar und ich finde ums verrr... nicht warum das nicht funktionieren sollte.


Ich nehme auch gerne Ideen wie ich der Sache auf die Spur kommen könnte.

WICHTIG !! Wenn ihr Testen wollt braucht ihr vom Package JvclLaz mindestens die Komponente jvpagecompsd.lpk (über OPM zu beziehen) und müsst sie noch mit der aktuellen Version von wp_xyz überschreiben die ihr von
https://sourceforge.net/p/lazarus-ccr/s ... PageComps/
beziehen könnt.
Dateianhänge
ctGUI_test.zip
(238.32 KiB) 161-mal heruntergeladen

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

Re: ctGUI (Tabbed GUI auf Basis JvTabBar)

Beitrag von wp_xyz »

Nimm mal aForm.Release - das zerstört des Formular mit Hilfe einer Warteschlange erst später, wenn all die laufenden Aktionen abgeschlossen sind.

charlytango
Beiträge: 1184
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: ctGUI (Tabbed GUI auf Basis JvTabBar)

Beitrag von charlytango »

Hervorragender Tipp -- es klappt -- THX

Wieder etwas gelernt ;-)

charlytango
Beiträge: 1184
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: ctGUI (Tabbed GUI auf Basis JvTabBar)

Beitrag von charlytango »

Nachdem ich einige Klippen umschiffen konnte kann ich euch eine erste Version meiner ctGUI vorstellen.
Sie ist derzeit als Singleton-Objekt realisiert und kann daher von überall in einer Applikation leicht "angegriffen" werden.
Ideen, Hinweise, Erfahrungen sind gerne gesehen.

Wer es ausprobieren möchte muss zumindest das jvPagecompsd.lpk Paket aus den Jvcllaz Package installieren. Da ich aktuell nicht nachgesehen habe ob wp_xyz schon die aktuelle Version im OPM hat, lege ich eine Version bei.

Die Downside ist allerdings das ich bei den Anchoreinstellungen nicht weiter komme, obwohl sie eigentlich logisch sein sollten.

Im Original JvTabBar gibt es eine Einstellung zur Orientierung ob der Bar oben oder unten sein soll. Nun kommt auch noch ein TToolbar dazu und das ist imho sauber nur mit anchoring zu lösen.

Die relevanten Prozeduren sind in der Unit ctGUI_class und heißen sinnigerweise SetAnchorTop und SetAnchorBottom.

Ich habe sie an den Beginn des Codes geschoben damit ihr nicht suchen müsst.

Die Einstellungen in SetAnchorTop scheinen zu funktionieren, die für das Bottom Design bekomme ich nicht hin. Da wäre Hilfe gefragt.

wenn das klappt stelle ich die erste Version mal auf Github
Dateianhänge
ctGUI_Demo.zip
(321.06 KiB) 73-mal heruntergeladen
JvPageComps.zip
(53.7 KiB) 63-mal heruntergeladen

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

Re: ctGUI (Tabbed GUI auf Basis JvTabBar)

Beitrag von wp_xyz »

So funktioniert's bei mir:

Code: Alles auswählen

procedure TctGUI.SetAnchorTop;
begin
  with Toolbar do begin
    Align := alNone;
    AnchorSideTop.Control := self;
    AnchorSideRight.Control := self;
    AnchorSideRight.Side := asrRight;
    AnchorSideBottom.Control := nil;
    Anchors := [akTop, akRight];
  end;

  with JvTabBar do begin
    Align := alNone;
    AnchorSideTop.Control := Self;
    AnchorSideLeft.Control := Self;
    AnchorSideRight.Control := ToolBar;
    AnchorSideRight.Side := asrLeft;
    AnchorSideBottom.Control := Toolbar;
    AnchorSideBottom.Side := asrBottom;
    Anchors := [akTop, akLeft, akRight, akBottom];
    Orientation := toTop;
  end;

  with JvPageList do begin
    AnchorSideLeft.Control := Self;
    AnchorSideRight.Control := Self;
    AnchorSideRight.Side := asrRight;
    AnchorSideTop.Control := JvTabBar;
    AnchorSideTop.Side := asrBottom;
    AnchorSideBottom.Control := self;
    anchorSideBottom.Side := asrBottom;
    Anchors := [akLeft, akRight, akTop, akBottom];
  end;
end;

procedure TctGUI.SetAnchorBottom;
begin
  with Toolbar do begin
    Align := alNone;
    AnchorSideBottom.Control := self;
    AnchorSideBottom.Side := asrBottom;
    AnchorSideRight.Control := self;
    AnchorSideRight.Side := asrRight;
    AnchorSideTop.Control := nil;
    Anchors := [akBottom, akRight]
  end;

  with JvTabBar do begin
    Align := alNone;
    AnchorSideLeft.Control := Self;
    AnchorSideRight.Control := ToolBar;
    AnchorSideRight.Side := asrLeft;
    AnchorSideBottom.Control := Self;
    AnchorSideBottom.Side := asrBottom;
    AnchorSideTop.Control := Toolbar;
    AnchorSideTop.Side := asrTop;
    Anchors := [akLeft, akRight, akBottom, akTop];
    Orientation := toBottom;
  end;

  with JvPageList do begin
    AnchorSideLeft.Control := Self;
    AnchorSideRight.Control := Self;
    AnchorSideRight.Side := asrRight;
    AnchorSideTop.Control := Self;
    AnchorSideTop.Side := asrTop;
    AnchorSideBottom.Control := JvTabBar;
    anchorSideBottom.Side := asrTop;
    Anchors := [akLeft, akRight, akTop, akBottom];
  end;
end;

charlytango
Beiträge: 1184
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: ctGUI (Tabbed GUI auf Basis JvTabBar)

Beitrag von charlytango »

Herzlichen Dank fürs Arsch retten !!!

Was meinst du, ist es den Aufwand wert daraus noch ein Package bzw eine Komponente zu machen ?
Du hast mir schonmal abgeraten.
Ein Runtime Package sollte aber kein Problem sein -- oder doch ?

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

Re: ctGUI (Tabbed GUI auf Basis JvTabBar)

Beitrag von wp_xyz »

Neues Package > in den Package-Eigenschaften RunTime-Unit setzen > die Units hinzufügen - ich denke das wars.

Ein Designtime-Package könnte man natürlich auch machen, aber hier sehe ich das Problem mit dem Singleton. Warum überhaupt ein Singleton? Schließt das nicht aus, dass ein Projekt mehrere Formulare mit je einem eigenen ctGui haben kann?

Mathias
Beiträge: 7056
Registriert: Do 2. Jan 2014, 17:21
OS, Lazarus, FPC: Linux (die neusten Trunk)
CPU-Target: 64Bit
Wohnort: Schweiz

Re: ctGUI (Tabbed GUI auf Basis JvTabBar)

Beitrag von Mathias »

Ein Runtime Package sollte aber kein Problem sein -- oder doch ?
Einfache Packages sind kein Problem, ich verwende dies viel lieber, als nackte Units, wo man bei jedem Project die Unit-Pfade eingeben muss.
Mit Lazarus sehe ich grün
Mit Java und C/C++ sehe ich rot

charlytango
Beiträge: 1184
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: ctGUI (Tabbed GUI auf Basis JvTabBar)

Beitrag von charlytango »

wp_xyz hat geschrieben: Mo 29. Sep 2025, 14:14 Ein Designtime-Package könnte man natürlich auch machen, aber hier sehe ich das Problem mit dem Singleton. Warum überhaupt ein Singleton? Schließt das nicht aus, dass ein Projekt mehrere Formulare mit je einem eigenen ctGui haben kann?
Nur soweit ich das mit dem Singleton verstanden habe(kann auch ganz anders sein):

Mittels Singleton-Funktion holt man sich immer wieder das selbe Objekt bzw man spricht immer das selbe Objekt an. Für mich der Vorteil ist, dass ich keine Public-Variablenverwaltung brauche weil ich quasi immer wieder das selbe "Public" objekt bekomme.
Das ist in der ganzen Applikation (wenn ich zum Aufruf die Singleton-Funktion verwende) immer das selbe.

Das funktioniert für mich perfekt für Objekte die man in der ganzen Applikation braucht (zb Datenbankanbindung, Einstellungen, GUI et al.)

Diese Strategie verhindert aber IMHO nicht dass ich mit

Code: Alles auswählen

procedure NocheineGUI;
var
TheNextctGUI: TctGUI;
begin
   TheNextctGUI:=TctGUI.Create(anyobject);
end;
beliebig viele Objekte vom Typ TctGUI quasi "zu Fuß" erstellen könnte.
Wobei .... ob mehrere GUIs in einer Applikation Sinn machen, wird der Anwendungsfall entscheiden. Vermutlich ist das eher selten, aber doch auch machbar.

charlytango
Beiträge: 1184
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: ctGUI (Tabbed GUI auf Basis JvTabBar)

Beitrag von charlytango »

irgendwie nervt mich der Change Prozess der Tabs bzw der JvPagelist.
Ich suche nach dem richtigen Event um das Wechseln der Tabs zu verhindern und zwar durch Attribute der Source-Page.
zb wenn Daten erst gespeichert werden müssen bevor ein Wechsel erlaubt wird.
Das Event das mir am sinnvollsten erschien, ist OnChanging der JvTablist.

Code: Alles auswählen

TJvPageChangingEvent = procedure(Sender: TObject; PageIndex: Integer; var AllowChange: Boolean) of object;


Sender ist die JvTablist
PageINdex ist der Index der neuen Zielpage

Wenn ich AllowChange auf false setze scheint es das verhalten nicht zu beeinflussen.
Der Tab wird gewechselt, auch wenn AllowChange False ist.

Gibt es eine Möglichkeit die Applikation so zu kompilieren dass ich das Package debuggen kann?

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

Re: ctGUI (Tabbed GUI auf Basis JvTabBar)

Beitrag von wp_xyz »

charlytango hat geschrieben: Sa 4. Okt 2025, 19:50 Gibt es eine Möglichkeit die Applikation so zu kompilieren dass ich das Package debuggen kann?
In den Projekt-Optionen, "Additions and Overrides", eine neue Option -gw3 definieren, damit werden alle vom Projekt benötigten Packages mit Dwarf3-Debuginformationen kompiliert. Dauert ein bisschen, auch wenn das nächste Projekt ohne diese Option kompiliert wird..
charlytango hat geschrieben: Sa 4. Okt 2025, 19:50 Wenn ich AllowChange auf false setze scheint es das verhalten nicht zu beeinflussen.
Der Tab wird gewechselt, auch wenn AllowChange False ist.
Sieht mir nach einen generellen Design-Fehler aus, da mMn das zu spät aufgerufen wird. Es gibt aber noch ein Event TTabBar.OnTabSelecting, da wird der Tab-Wechsel unterbunden, wenn AllowSelect = false ist.

charlytango
Beiträge: 1184
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: ctGUI (Tabbed GUI auf Basis JvTabBar)

Beitrag von charlytango »

wp_xyz hat geschrieben: Sa 4. Okt 2025, 20:15 Sieht mir nach einen generellen Design-Fehler aus,
Du meinst einen Design Fehler in der JvPagelist oder bei mir?
Ich werde noch das OnTabSelecting Event testen

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

Re: ctGUI (Tabbed GUI auf Basis JvTabBar)

Beitrag von wp_xyz »

Man kriegt das Event TJvPageList.OnChanging Event zum Laufen, indem man TJvCustomTabBar vor der Änderung des aktiven Tab abfragen lässt, ob PageList.CanChange die Änderung erlaubt:

Code: Alles auswählen

function TJvCustomTabBar.TabSelecting(Tab: TJvTabBarItem): Boolean;
var
  PageListIntf: IPageList;
begin
  Result := True;
  if Assigned(FOnTabSelecting) then
    FOnTabSelecting(Self, Tab, Result);
  if Result and (PageList <> nil) and Supports(PageList, IPageList, PageListIntf) then   // <--- neu...
  begin
    Result := PageListIntf.CanChange(Tab.Index);
    PageListIntf := nil;
  end;                                                                                   // ... bis hier
end; 
Keine Ahnung, warum die JVCL-Autoren dafür zwei Events vorgesehen haben... Könnte sein, dass mit dieser Änderung neue Bugs entstanden sind. Da du zur Zeit wohl der intensivste Tester von TJvTabBar bist, wäre ich um Rückmeldung dankbar, bevor ich diese Änderung fest einbaue.

charlytango
Beiträge: 1184
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: ctGUI (Tabbed GUI auf Basis JvTabBar)

Beitrag von charlytango »

lass dir bitte noch etwas Zeit, ich hab das Teil auch so zur Mitarbeit überredet.
ich sehe mit deine Lösung auch noch genauer an

JvTabBar.OnSelecting := @JvTabBarTabSelecting;

Code: Alles auswählen

procedure TctGUI.JvTabBarTabSelecting(Sender: TObject; Item: TJvTabBarItem;
  var AllowSelect: Boolean);
var
  aSourceForm:TForm;
  iSourceIndex:integer;
begin
  AllowSelect:=true;
    if not assigned(Sender) or (Sender=nil) then exit;
    if TJvTabBar(Sender).Tabs.Count < 1 then exit;
    if not assigned(TJvTabBar(Sender).SelectedTab) or (TJvTabBar(Sender).SelectedTab=nil) then exit;

    iSourceIndex:=   TJvTabBar(Sender).SelectedTab.Index;
    aSourceForm := TForm(FJvPageList.Pages[iSourceIndex].Tag);
    
    AllowSelect := CanLeavePage(aSourceForm);
end; 

function TctGUI.CanLeavePage(aForm: TForm): boolean;
begin
  result:=true;
  if not assigned(aForm) or (aForm=nil) then exit;

   if aForm is TctGUIParentForm then begin
     result:= TctGUIParentForm(aForm).CanChange; //Fragt die eingeklebte Seite ab ob gewechselt weden darf
   end
   else
     //CallBoolMethod(aForm,'CanChange',AllowChange)
   ;

end; 

charlytango
Beiträge: 1184
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: ctGUI (Tabbed GUI auf Basis JvTabBar)

Beitrag von charlytango »

Durch die Teilung von TabBar und Pagelist wollten die Autoren wohl zwei Fliegen mit einer Klappe schlagen, um TPageControl und TTabControl aufzupeppen. Damit sind halt auch andere Herausforderungen entstanden.
Ich finde die Optik wesentlich besser und mittlerweile hab ich mich etwas an die Bedienung gewöhnt.

Für die Zwecke von ctGUI brauche ich quasi die Erlaubnis der eingeklebten Seite, ob der User die Seite verlassen/wechseln kann.

Es heißen auch die Events unterschiedlich
im TabBar: "Select"
in der PageList: "Change"

Für mich übersetzt bedeuted deine Strategie dass vor dem Ansteuern eines neuen Tabs im OnTabSelecting Event nachgesehen wird ob das erlaubt ist und -- falls eine Pagelist zugeordnet ist -- auch in dieser im OnChange nachgefragt wird ob das passt.

Antworten