Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   GUI-Design mit VCL / FireMonkey / Common Controls (https://www.delphipraxis.net/18-gui-design-mit-vcl-firemonkey-common-controls/)
-   -   Panel Zentrieren... (https://www.delphipraxis.net/207782-panel-zentrieren.html)

Delbor 2. Mai 2021 15:45

Panel Zentrieren...
 
Liste der Anhänge anzeigen (Anzahl: 1)
Hi zusammen

Ich hab jetzt länger gesucht, aber keine Antwort auf mein Problem gefundn. Mein erster gedanke: Es liegt an unterschiedlichen Koordinatensystemen. Die antwort wäre wohl ParentToClient oder umgekehrt.
Bloss - wie bringe ich Client.Width und Parent.Padding "zusammen" ?

Mein Ansatz (ohne TGridPanel...):
Delphi-Quellcode:
function TPnlCalendarFrame.GetParentControlPostion(AParentCtrl : TPanel): integer;
  var Widthtotal : Word;
begin
  Widthtotal := (6 * FDayNumberFrame.Width);
  Result := (AParentCtrl.ClientWidth div 2) - (Widthtotal div 2);
end;


procedure TPnlCalendarFrame.CreateDayNumberFrame(AMonth: Integer);
  var LMonat, LName :String; LYear, LMonth, LDay : Word;
begin
  System.SysUtils.DecodeDate(FFirstMonthDay, LYear, LMonth, LDay);
  FDayNumberFrame := TDayNumberFrame.Create(Self);
  LMonat := Monate[AMonth];
  LName := LMonat + 'Frame';
  case AMonth of
    1..6: begin
            FParentCtrl := PnlSixMonts1;
            FParentCtrl.Padding.Left := GetParentControlPostion(FParentCtrl);
          end;
    7..12:begin
            FParentCtrl := PnlSixMonts2;

          end;
  end;
  FDayNumberFrame.LblCaption.Caption := LMonat;
  FDayNumberFrame.Name := LName;
  FDayNumberFrame.InitDayNumberFrame;
  FDayNumberFrame.FirstMonthDay := StartOfAMonth(LYear, AMonth);
  FDayNumberFrame.LastMonthDay := EndOfAMonth(LYear, AMonth);
  FDayNumberFrame.Parent := FParentCtrl;
  FDayNumberFrame.Align := alLeft;
  FDayNumberFrame.Visible := true;
  FDayNumberFrame.HorzDayNumbersMonths;
end;
Und so schauts dann aus:
Anhang 53937

Dass die Reihenfolge der Monate durcheinanderkommt, bemerke ich auch erst jetzt...
Dass das Monatspanel über den linken Rand hinausragt, führe ich auf die unterschiedlichen Koordinatensysteme beider Panels zurück. Das schreit nach ClienttoParent... Blos: wie bringt man TPoint und integer (AParentCtrl.ClientWidth) zusammen?

Gruss
Delbor

KodeZwerg 2. Mai 2021 15:56

AW: Panel Zentrieren...
 
Delphi-Quellcode:
Widthtotal := (6 * FDayNumberFrame.Width) + (6 * (margins.left + margins.right));
?

Delbor 2. Mai 2021 16:01

AW: Panel Zentrieren...
 
Hi KodeZwerg

Danke für deine Antwort!
AlignwithMargins ist in allen irgendwie beteiligten Komponenten false.

Gruss
Delbor

KodeZwerg 2. Mai 2021 16:15

AW: Panel Zentrieren...
 
Es scheint sich ja um eine art Komponente zu handeln die du da bastelst wo noch an manchen stellen dinge falsch laufen.
Visuell würde ich es so machen wie der Windows Kalender es macht.
(Immer 31 Felder rein, "in grau" vor-monat bzw nächster-monat felder. Das du die KW visuell mit aufnimmst ist ein nettes gimmick!)
Für eine bessere Reparatur / alternative vorgehensweisen, würde ich den kompletten source mal anheften.
(Ich pers. würde zBsp immer nur einen Monat darstellen lassen, das vereinfacht den Umgang denk ich mal enorm da man ja weiß wieviel felder es sind)

Uwe Raabe 2. Mai 2021 16:45

AW: Panel Zentrieren...
 
Zitat:

Zitat von Delbor (Beitrag 1488437)
AlignwithMargins ist in allen irgendwie beteiligten Komponenten false.

Dann wird Padding aber auch nicht ausgewertet.

Delbor 2. Mai 2021 17:08

AW: Panel Zentrieren...
 
Liste der Anhänge anzeigen (Anzahl: 3)
Hi Kodezwerg

Anbei im Anhang mal der Kalenderframe - der zeigt tatsächlich jeweils einen Monat an, führt aber zusätzlicj noch die letzten Tage des Vor- und die ersten Tage des Nachfolgemonats, sofern sie in eine Woche fallen, die auch zum aktuell angezeigten Monat gehört:
Anhang 53940
Anhang 53938
Anhang 53939

Gruss
Delbor

Delbor 2. Mai 2021 17:24

AW: Panel Zentrieren...
 
Liste der Anhänge anzeigen (Anzahl: 1)
Hi Uwe Raabe

Zitat:

Zitat von Uwe Raabe (Beitrag 1488439)
Zitat:

Zitat von Delbor (Beitrag 1488437)
AlignwithMargins ist in allen irgendwie beteiligten Komponenten false.

Dann wird Padding aber auch nicht ausgewertet.

Seit wann denn das? Das hätte ich bei all meinen Versuchen bemerken müssen. Margins verwende ich in der Regel nur, wenn 2 AlTop ausgerichtete Panels(..) nicht nur zum Parent abstand halten sollen, sondern auch untereinander. Allerdings gibt es keinen Boolean und keine vorbelegten Werte wie bei margins.
Anhang 53941
Margins ist so Standard, während Padding standardmässig null ist und hier von mir belegt wurde.

Gruss
Delbor

himitsu 2. Mai 2021 18:52

AW: Panel Zentrieren...
 
Paddings werden eigentlich immer angewendet. (jedenfalls bisher noch nie irgendwo gesehen, dass es nicht so war)

Bei den Margins sieht es aber anders aus, denn die werden böswillig ignoriert, außer man setzt ganz oben das Häkchen bei AlignWithMargins (aber darauf muß man erstmal kommen).

KodeZwerg 2. Mai 2021 19:11

AW: Panel Zentrieren...
 
Sollte dann das padding nicht noch mit reingerechnet werden bei "Widthtotal", rein vom logischen Aspekt?
Ich spiele eigentlich nur mit margins rum. Durch on/off find ich es flexibler.

Uwe Raabe 2. Mai 2021 23:02

AW: Panel Zentrieren...
 
Zitat:

Zitat von himitsu (Beitrag 1488447)
Paddings werden eigentlich immer angewendet.

Stimmt. Ich hatte da etwas anderes im Sinn, sorry.

Delbor 3. Mai 2021 12:37

AW: Panel Zentrieren...
 
Hi zusammen

Ich habe gerade gesehen, dass die drei *.pas- Dateien bislang dreimal angeklickt, bzw. wahrscheinlich drei mal gedownloaded wurden. Habt ihr dabeieine Antwort gefunden?

Gruss
Delbor

KodeZwerg 3. Mai 2021 15:06

AW: Panel Zentrieren...
 
Zitat:

Zitat von Delbor (Beitrag 1488491)
Habt ihr dabeieine Antwort gefunden?

Ich konnte mit den Units noch nichts anfangen da mir RzTabs(?) unit fehlt. Noch keine Zeit gehabt das auseinander-zu-pflücken um es irgendwie nutzbar zu machen.

Delbor 3. Mai 2021 15:38

AW: Panel Zentrieren...
 
Hi CodeZwerg

Der Termineingabeframe enthält keinen Code. Wenn der also nicht gefunden wird, kannst du die entsprechende Referenz darauf einfach löschen lassen.
Andrerseits könntest du dir die Raize-Components gratis von Embarcadero Downloaden. Allenfalls geht das mit der Communitie nicht.

Die Komponenten sind etwas besser als die Standards - die Tabsheets des PageControls lassen sich einfärben, die Reiter haben verschiedene Formen/Ecken oder auch nicht.

Einfach die Pas in ein Beispielprojekt kopieren (NICHT UMBENENNEN) und dem Projekt hinzufügen.

Gruss
Delbor

Delbor 4. Mai 2021 12:00

AW: Panel Zentrieren...
 
Liste der Anhänge anzeigen (Anzahl: 2)
Hi zusammen

Das ist der PnlCalendaframe zur Designzeit :
Anhang 53955
clAqua sind dabei die beiden Panels, die je 6 Monatsframes aufnehmen. Width dieser Panels ist Widthtotal.
AParentCtrl ist das blaue Panel.

Und das ist das, wasmir zur Laufzeit gemeldet wird:
Zitat:

[Window Title]
Terminkalenderproject

[Content]
FDayNumberFrame.Width := 260 <== die sechs Monats-Kalender
AParentCtrl.Width := 1320 <== Der blaue Panel
Widthtotal := 1560 <== alle sechs Monatskalender
FDayNumberFrame.Width := 260
GetParentControlPostion := -240

[OK]
Und das ist der Frame zur Laufzeit:
Anhang 53956

Withtotal ist also grösser als das umgebende Panel. Also 2 verschiedene Koordinatensysteme? Und nun?

Gruss
delbor

himitsu 4. Mai 2021 12:16

AW: Panel Zentrieren...
 
Andere spezille Ausrichtungkomponenten hast du auch mal ausprobiert?

Suche mal in der Komponenten nach Dingen mit "Panel" im Namen.
TGridPanel, TFlowPanel, TRelativePanel, ...


Im FMX nennen die sich "Layout".

Rollo62 4. Mai 2021 12:37

AW: Panel Zentrieren...
 
Zitat:

Zitat von himitsu (Beitrag 1488552)
Im FMX nennen die sich "Layout".

Nicht ganz, da gibt es auch ein TPanel.
TLayout sollte man als Container nehmen für andere Controls, das zeichnet sich nicht selbst und ist sehr schlank.
TPanel gehr aber auch, ist halt auch selbst ein Control.

Delphi.Narium 4. Mai 2021 12:38

AW: Panel Zentrieren...
 
Delphi-Quellcode:
...
  case AMonth of
    1..6: begin
            FParentCtrl := PnlSixMonts1;
            // Beim ersten Panel machst Du das und das Ergebnis stimmt.
            FParentCtrl.Padding.Left := GetParentControlPostion(FParentCtrl);
          end;
    7..12:begin
            FParentCtrl := PnlSixMonts2;
            // Beim zweiten Panel machst Du das nicht und das Ergebnis stimmt nicht.
            FParentCtrl.Padding.Left := GetParentControlPostion(FParentCtrl);
          end;
  end;
...
end;
Wäre das eine Möglichkeit?
Delphi-Quellcode:
...
  case AMonth of
    1.. 6: FParentCtrl := PnlSixMonts1;
    7..12: FParentCtrl := PnlSixMonts2;
  end;
  FParentCtrl.Padding.Left := GetParentControlPostion(FParentCtrl);
...

stahli 4. Mai 2021 12:42

AW: Panel Zentrieren...
 
Bei solchen komplexeren Positionierungen würde ich das lieber selbst berechnen, also keine Aligns, Paddings und Margins benutzen.
Das wird insgesamt schneller sein und Du hast keine unübersichtlichen gegenseitigen Beeinflussungen.

Du kannst gezielt gewünschte Abstände einberechnen und die z.B. auch verringern, falls der Platz etwas knapper wird.
Auch das Zentrieren horizontal und vertikal ist kein Problem.

Natürlich musst Du dafür eine Funktion schreiben, aber das ist ein einmaliger Aufwand.
Aufrufen musst Du sie einmal bei der Initialisierung und dann im OnResize.

Dann hast Du alles selbst in der Hand und musst nicht mit Überraschungen der VCL umgehen.

Delbor 4. Mai 2021 13:51

AW: Panel Zentrieren...
 
Hi zusammen
Zuerst mal recht vielen Dank für eure vielen Antworten!
Zitat:

Zitat von himitsu (Beitrag 1488552)
Andere spezille Ausrichtungkomponenten hast du auch mal ausprobiert?

Suche mal in der Komponenten nach Dingen mit "Panel" im Namen.
TGridPanel, TFlowPanel, TRelativePanel, ...

Ja,danke. Habe ich, bis auf TRelativpanel: Letzteres hab ich mir nur mal die Demo angesehen, während ich nach einer solchen suchte:TGridpanel, und von TFlowPanel habe ich auch eine Demo durchgearbeitet. Vielleicht mit gewissen Nuancen hab ich überall das selbe Problem: alle kleben standardmässig immer in Left.
Bei TGridpanel habe ich keinen Wert für den Abstand zischen zwei Controls gefunden, bei TFlowpanel ist es wohl mehr oder weniger dasselbe.

Zitat:

Zitat von Delphi.Narium (Beitrag 1488554)
Wäre das eine Möglichkeit?
Delphi-Quellcode:
...
  case AMonth of
    1.. 6: FParentCtrl := PnlSixMonts1;
    7..12: FParentCtrl := PnlSixMonts2;
  end;
  FParentCtrl.Padding.Left := GetParentControlPostion(FParentCtrl);
...

Hab ich bereits so umgesetzt, steht so korrigiert aber nicht in der bereitgestellten *.pas. Was da (auch bei mir) noch fehlt: FParentCtrl hat von 1..6 einen andern Wert als von 7...12, wird also die ersten 6 mal überschrieben.

Zitat:

Zitat von stahli (Beitrag 1488555)
Bei solchen komplexeren Positionierungen würde ich das lieber selbst berechnen, also keine Aligns, Paddings und Margins benutzen.
Das wird insgesamt schneller sein und Du hast keine unübersichtlichen gegenseitigen Beeinflussungen.

Du kannst gezielt gewünschte Abstände einberechnen und die z.B. auch verringern, falls der Platz etwas knapper wird.
Auch das Zentrieren horizontal und vertikal ist kein Problem.

Natürlich musst Du dafür eine Funktion schreiben, aber das ist ein einmaliger Aufwand.
Aufrufen musst Du sie einmal bei der Initialisierung und dann im OnResize.

Dann hast Du alles selbst in der Hand und musst nicht mit Überraschungen der VCL umgehen.[/QUOTE]


Grundsätzlich stimme ich dir zu. Eine Besonderheit von Align ist zB., dass sich eine Komponente, die alLeft ausgrichtet werden soll, vor eine alLeft ausgerichtete Komponente schiebt. Bei mir kann das dann plötzlich heissen, dass der Februar vor dem Januar kommt...
Aber da sind auch die Werte, die ich zur Laufzeit ermittle und die den sichtbaren Panels total wiedersprechen.
Im "untersten" Frame, dem FDayNumberFrame, sind keinerlei Margins oder Paddings gesetzt: das Ding muss mit absolut minimalem Platz auskommen.
Ansonsten müsste ich mir das nochmal genau vornehmen...

Gruss
Delbor

Delphi.Narium 4. Mai 2021 14:05

AW: Panel Zentrieren...
 
Wenn ich was links anordnen will, aber nicht ganz links, sondern rechts neben dem letzten ganz links, helfe ich mir in der Art:
Delphi-Quellcode:
Panel.Align := alRight; // Schiebt erstmal nach ganz rechts.
Panel.Align := alLeft; // Schiebt nun nicht nach ganz links, sondern rechts neben das "letzte" der links angeordeneten Elemente.

// oder:
Panel.Align := alLeft; // Schiebt nach ganz links.
Panel.Left := Parent.Width; // Verschiebt nach vielzuweit rechts, da aber Align = alLeft ist, wird daraus rechts neben dem "Letzten" links.

// oder:
Panel.Left := MaxInt; // Verschiebt nach vielzuweit rechts, da aber Align = alLeft ist, wird daraus rechts neben dem "Letzten" links.
Panel.Align := alLeft; // Schiebt nach ganz links. neben dem "Letzten" links.

// oder:
// In umgekehrter Reihenfolge einfügen.
// Zuerst das, was im Ergebnis am weitesten rechts sein soll.
// Dann das davor
// und dann das davor
// ...
// Hieße bei Dir also einfügen von
// Juni
// Mai
// April
// März
// Februar
// Januar

KodeZwerg 4. Mai 2021 14:19

AW: Panel Zentrieren...
 
Zitat:

Zitat von Delbor (Beitrag 1488566)
Eine Besonderheit von Align ist zB., dass sich eine Komponente, die alLeft ausgrichtet werden soll, vor eine alLeft ausgerichtete Komponente schiebt.

Da hilft ein einfacher Trick:
Element1.Left := 0;
Element2.Left := 1;
Element3.Left := 2;
usw usf.

himitsu 4. Mai 2021 15:31

AW: Panel Zentrieren...
 
Ja, beim GritPanel selber gibt es leider keinen Wert für den Zellenabstand.

Wenn die enthaltenen Komponenten kleiner als eine Zelle sind (nicht mit alClient eingepasst), dann zentrieren sie sich selbst.

Aber man könnte auch mit alClient und den Margins (AlighWithMargins=True nicht vergessen), an jeder Komponente, einen Abstand einstellen.
Entweder jeweils ein halber Abstand (lins X/2 und rechts X/2) an jeder Komponente oder blos einseitig an den Nachbarkomponenten (z.B. links X und rechts 0)

Delbor 4. Mai 2021 16:13

AW: Panel Zentrieren...
 
Hi himitsu
Zitat:

Zitat von himitsu (Beitrag 1488573)
Aber man könnte auch mit alClient und den Margins (AlighWithMargins=True nicht vergessen), an jeder Komponente, einen Abstand einstellen.
Entweder jeweils ein halber Abstand (lins X/2 und rechts X/2) an jeder Komponente oder blos einseitig an den Nachbarkomponenten (z.B. links X und rechts 0)

Soviel ich mich an meine Versuche mit dem Gridpanel zurückerinnere, hatte ich lange Zeit Paddingwerte vergeben, und diese Werte beeinflussten nicht nur den inneren Rand, sondern auch die Zwischenräume.
Ich muss mir das nochmal ansehen, aber wenn ichs richtig in Erinnerung habe: ohne Paddingwerte waren die Zwischenräume nur noch wenige Pixel, während die Aussenabstände innen (normalerweise das Padding) nicht null, aber auch nicht wirklich vorhanden zu sein schienen.
Wegen der fehlenden Werte der Zwischenräume konnte ich auch keine Aussenabstände errechnen, beziehungsweise das Gridpanel auf seinem Parent nicht einmitten.
Auch hier gilt: sobald ich das Gridpanel versuchte, einzumitten ((parent.width - Gridpanel.width) div 2)überlappte es links. Auch hier war offensichtich der Parent "kürzer" als das Gridpanel.

Gruss
Delbor

stahli 4. Mai 2021 16:33

AW: Panel Zentrieren...
 
Vielleicht arbeitest Du manchmal noch fälschlicher Weise mit Width statt ClientWidth und kommst aus solchen Gründen nicht ganz zurecht...

Delbor 4. Mai 2021 20:06

AW: Panel Zentrieren...
 
Hi Stahli

Ein ShowMessage:
Zitat:

[Window Title]
Terminkalenderproject

[Content]
FDayNumberFrame.Width := 260
AParentCtrl.Width := 1314
AParentCtrl.ClientWidth := 1314
Widthtotal := 1560
FDayNumberFrame.Width := 260
GetParentControlPostion := -246

[OK]
und wie es zustande kommt:

Delphi-Quellcode:
function TPnlCalendarFrame.GetParentControlPostion(AParentCtrl : TPanel): integer;
  var Widthtotal : Word;
begin
  Widthtotal := (6 * FDayNumberFrame.Width);
  Result := (AParentCtrl.ClientWidth - Widthtotal);
  ShowMessage('FDayNumberFrame.Width := ' + InttoStr(FDayNumberFrame.Width) + slinebreak+
              'AParentCtrl.Width := ' + InttoStr(AParentCtrl.Width) + slinebreak+
              'AParentCtrl.ClientWidth := ' + InttoStr(AParentCtrl.ClientWidth) + slinebreak+
              'Widthtotal := ' + InttoStr(Widthtotal) + slinebreak+
              'FDayNumberFrame.Width := ' + InttoStr(FDayNumberFrame.Width) + slinebreak+
              'GetParentControlPostion := ' + InttoStr(Result));
end;
Hochinteressant dabei: Zeile2 und 3 aus der ShowMessage-Anweisung.

Gruss
Delbor

Delbor 5. Mai 2021 14:30

AW: Panel Zentrieren...
 
Liste der Anhänge anzeigen (Anzahl: 3)
Hii zusammen

Ich glaube, ich habe den übeltäter gefunden der Basisframe...
Aber erstmal beim Create der Mainform:
Delphi-Quellcode:
procedure Ta.FormCreate(Sender: TObject);
   var i: integer; LEnvirontVariable: String;
begin
  Self.PnlCalendarFrame1.PnlCalendarPosition;
  Self.PnlCalendarFrame1.PnlSixMonths1Position;
  Self.PnlCalendarFrame1.PnlSixMonths2Position;
  Self.PnlCalendarFrame1.ChooseMonths;
end;
Da geschieht noch mehr, was aber mit dem aktuellen Thema nichts zu tun hat. In jedem Fall handelt essich um Test mit jeweilseigenen Objekten.
Weiter gehts mit den aufgerufenen Methoden:

Delphi-Quellcode:
procedure TPnlCalendarFrame.PnlCalendarPosition;
begin
  PnlCalendarPos.Left := 0;
  Top :=0;
//  PnlCalendarPos.Width := PnlCalendarPos.Parent.ClientWidth;
  PnlCalendarPos.Width := Self.Width;
//  PnlCalendarPos.Width := Self.ClientWidth;
end;
Als "Interessant" herausgestellt hat sich eigentlich die obige Prozedur. Ich habe hier abwechslungsweise Zeilen ausgeklammert, um deren "Wirksamkeit zu testen.

Delphi-Quellcode:
procedure TPnlCalendarFrame.PnlSixMonths1Position;
begin
  PnlSixMonts1.Left := 0;
  PnlSixMonts1.Top := 0;
  PnlSixMonts1.Width := 6*300;     // Diese 300 sind der von Hand aufgerundeten
  PnlSixMonts1.Height := 174;      // Wert FDayNumberFrame.Width (257)
end;

procedure TPnlCalendarFrame.PnlSixMonths2Position;
begin
  PnlSixMonts2.Left := 0;
  PnlSixMonts2.Top := PnlSixMonts1.Height;
//  PnlSixMonts2.Width := PnlCalendarPos.ClientWidth;
  PnlSixMonts2.Width := PnlSixMonts2.Parent.ClientWidth;
  PnlSixMonts2.Height := 174;
end;
Anhang 53958Anhang 53959
Das sind die Ergebnisse mit allen möglichen Codevarianten

Anhang 53960
Und das ist das Ergebnis, wenn ich zur Designzeit alle Hilfsfenster (Objectinspektor etc) ausblende und die Arbeitsform über möglichst die ganze Bildschirmbreite aufziehe.Ich habe nicht alle Codeteile korrekt angepasst. Desshalb die Ungleichheiten.
Ich verstehe das jetzt mal so, dass ohne Tricks (künstlich zugewiesene Masse) eine Frameinstanz nie grösser sein kann, als der benutzte BasisFrame zur Entwurfszeit - grosser Bildschirm hin oder her.
Als ich hierdran gearbeitet habe, war mein Gedanke erstmal: ich brauch die ganzen Panels gar nicht mehr. Aber sie machens auch so einfacher...
Tia, und wies nun weitergeht, hab ich erstmal keine Ahnung. 2 Panels links und rechts, die die Differenz DesignzeitBreite zur LaufzeitBreite ausgleichen?
Ich habe hier alle Margins und Paddings entfernt, mit Ausnahme des Titelpanels. Ob das tatsächlich notwendig ist, muss die Zukunft zeigen. Ich denke mir eigentlich: alles, was innerhalb der Masse des Basisframes liegt, sollte machbar sein.

Gruss
Delbor


Alle Zeitangaben in WEZ +1. Es ist jetzt 15:09 Uhr.

Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz