AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Zurück Delphi-PRAXiS Programmierung allgemein GUI-Design mit VCL / FireMonkey / Common Controls Delphi VirtualTreeview als Grid optimale Spaltenbreite berechnen
Thema durchsuchen
Ansicht
Themen-Optionen

VirtualTreeview als Grid optimale Spaltenbreite berechnen

Ein Thema von Codehunter · begonnen am 7. Mär 2023 · letzter Beitrag vom 8. Mär 2023
Antwort Antwort
Benutzerbild von Codehunter
Codehunter

Registriert seit: 3. Jun 2003
Ort: Thüringen
2.272 Beiträge
 
Delphi 10.4 Sydney
 
#1

VirtualTreeview als Grid optimale Spaltenbreite berechnen

  Alt 7. Mär 2023, 09:42
Hallo!

Nach langer Zeit hab ich mal wieder ein Problem an dem ich mir die Zähne ausbeiße:

Ich verwende einen VirtualTreeview als Grid. Dort wo ich das Grid initialisiere, stehen mir schon folgende Werte zur Verfügung:
  1. Spaltentitel (Headertext) jeder Spalte
  2. längster Grid-Celltext jeder Spalte

Ich versuche nun, bei der Initialisierung für jede Spalte die optimale Breite zu berechnen. Das Ziel soll sein, dass jede Spalte genau so breit ist, dass weder der Headertext noch die Zellenwerte mit "..." abgekürzt werden. Die Spalten sind zudem sortierbar, d.h. es kommt ggf. im Header noch das SortGlyph dazu.

Ich kann nun zwar mit Canvas.TextWidth die Breite des Headertextes sowie des längsten Zellentextes berechnen. Aber ich habe festgestellt, dass mit statischen "Zugaben" für Headerbreite und Zellenbreite kein Blumentopf zu gewinnen ist. Ich kriegs zwar hin dass alle Spalten ohne "..." angezeigt werden, aber manche sind viel zu breit.

Wenn ich mir z.B. in VirtualTrees.pas die TVirtualTreeColumn.ComputeHeaderLayout anschaue, dann ahne ich auch warum: Da stecken extrem komplizierte Berechnungen dahinter.

Nun frage ich mich: Hat der Virtualtree vielleicht schon eine eingebaute Funktion, die optimale Spaltenbreite zu berechnen, der ich den Headertext und den längsten Zellentext mitgeben kann?

Grüße
Cody
Ich mache grundsätzlich keine Screenshots. Schießen auf Bildschirme gibt nämlich hässliche Pixelfehler und schadet der Gesundheit vom Kollegen gegenüber. I und E zu vertauschen hätte den selben negativen Effekt, würde aber eher dem Betriebsklima schaden

Geändert von Codehunter ( 7. Mär 2023 um 09:46 Uhr)
  Mit Zitat antworten Zitat
Benutzerbild von KodeZwerg
KodeZwerg

Registriert seit: 1. Feb 2018
3.685 Beiträge
 
Delphi 11 Alexandria
 
#2

AW: VirtualTreeview als Grid optimale Spaltenbreite berechnen

  Alt 7. Mär 2023, 12:14
Ich habe den VST in Delphi leider nie installiert aber in Lazarus.
Dort gibt es "VST.Header.AutoFitColumns()" als Methode.
Delphi-Quellcode:
procedure TVTHeader.AutoFitColumns(Animated: Boolean = True; SmartAutoFitType: TSmartAutoFitType = smaUseColumnOption;
  RangeStartCol: Integer = NoColumn; RangeEndCol: Integer = NoColumn);

  //--------------- local functions -------------------------------------------

  function GetUseSmartColumnWidth(ColumnIndex: TColumnIndex): Boolean;

  begin
    Result := False;
    case SmartAutoFitType of
      smaAllColumns:
        Result := True;
      smaNoColumn:
        Result := False;
      smaUseColumnOption:
        Result := coSmartResize in FColumns.Items[ColumnIndex].FOptions;
    end;
  end;

  //----------------------------------------------------------------------------

  procedure DoAutoFitColumn(Column: TColumnIndex);

  begin
    with FColumns do
      if ([coResizable, coVisible] * Items[FPositionToIndex[Column]].FOptions = [coResizable, coVisible]) and
            DoBeforeAutoFitColumn(FPositionToIndex[Column], SmartAutoFitType) and not TreeView.OperationCanceled then
      begin
        if Animated then
          AnimatedResize(FPositionToIndex[Column], Treeview.GetMaxColumnWidth(FPositionToIndex[Column],
            GetUseSmartColumnWidth(FPositionToIndex[Column])))
        else
          FColumns[FPositionToIndex[Column]].Width := Treeview.GetMaxColumnWidth(FPositionToIndex[Column],
            GetUseSmartColumnWidth(FPositionToIndex[Column]));

        DoAfterAutoFitColumn(FPositionToIndex[Column]);
      end;
  end;

  //--------------- end local functions ----------------------------------------

var
  I: Integer;
  StartCol,
  EndCol: Integer;

begin
  StartCol := Max(NoColumn + 1, RangeStartCol);

  if RangeEndCol <= NoColumn then
    EndCol := FColumns.Count - 1
  else
    EndCol := Min(RangeEndCol, FColumns.Count - 1);

  if StartCol > EndCol then
    Exit; // nothing to do

  TreeView.StartOperation(okAutoFitColumns);
  try
    if Assigned(TreeView.FOnBeforeAutoFitColumns) then
      TreeView.FOnBeforeAutoFitColumns(Self, SmartAutoFitType);

    for I := StartCol to EndCol do
      DoAutoFitColumn(I);

    if Assigned(TreeView.FOnAfterAutoFitColumns) then
      TreeView.FOnAfterAutoFitColumns(Self);

  finally
    Treeview.EndOperation(okAutoFitColumns);
  end;
end;
Meintest Du sowas?
Gruß vom KodeZwerg
  Mit Zitat antworten Zitat
Benutzerbild von Codehunter
Codehunter

Registriert seit: 3. Jun 2003
Ort: Thüringen
2.272 Beiträge
 
Delphi 10.4 Sydney
 
#3

AW: VirtualTreeview als Grid optimale Spaltenbreite berechnen

  Alt 7. Mär 2023, 17:28
Jain. AutoFit habe ich auch probiert. Leider ist diese Methode extremst langsam bei meinen Datenmengen. Deshalb ermittle ich ja schon vorab, was der längste Zelleninhalt je Spalte ist. Da ich eine Monospace-Schriftart verwende ist die Anzahl Buchstaben gleichbedeutend mit der größten Pixelanzahl. Ich kann also schon beim Initialisieren des VST (Rootnodecount setzen und entsprechende Anzahl Column-Objekte erzeugen) festlegen, wie breit jede Spalte sein soll. Das würde ich gar nicht nachgelagert über Eventhandler machen wollen.

Der Knackpunkt ist der ColumnHeader mit dem Sort-Glyph. Wenn das beides zusammen mehr Platz braucht als der längste Zelleninhalt im Grid, klappt die Kalkulation nicht mehr. Warum auch immer.
Ich mache grundsätzlich keine Screenshots. Schießen auf Bildschirme gibt nämlich hässliche Pixelfehler und schadet der Gesundheit vom Kollegen gegenüber. I und E zu vertauschen hätte den selben negativen Effekt, würde aber eher dem Betriebsklima schaden
  Mit Zitat antworten Zitat
taveuni

Registriert seit: 3. Apr 2007
Ort: Zürich
526 Beiträge
 
Delphi 11 Alexandria
 
#4

AW: VirtualTreeview als Grid optimale Spaltenbreite berechnen

  Alt 8. Mär 2023, 10:26
Jain. AutoFit habe ich auch probiert. Leider ist diese Methode extremst langsam bei meinen Datenmengen. Deshalb ermittle ich ja schon vorab, was der längste Zelleninhalt je Spalte ist. Da ich eine Monospace-Schriftart verwende ist die Anzahl Buchstaben gleichbedeutend mit der größten Pixelanzahl. Ich kann also schon beim Initialisieren des VST (Rootnodecount setzen und entsprechende Anzahl Column-Objekte erzeugen) festlegen, wie breit jede Spalte sein soll. Das würde ich gar nicht nachgelagert über Eventhandler machen wollen.

Der Knackpunkt ist der ColumnHeader mit dem Sort-Glyph. Wenn das beides zusammen mehr Platz braucht als der längste Zelleninhalt im Grid, klappt die Kalkulation nicht mehr. Warum auch immer.
Du kannst beim Initialsieren die (Mindest-) Headerspaltenbreite berechnen mit Zugabe für den Glyph. Dann die Mindestbreite setzen.

Delphi-Quellcode:
procedure TFrameAlarmsVst.InitVst;
var
  col: TVirtualTreeColumn;
  b: TBitmap;
begin
  b:= TBitMap.Create;
  try
    b.Canvas.Font.Assign(vstAlarms.Header.Font);

    col:= self.vstAlarms.Header.Columns.Add;
    col.Text:= _('Alarmart');
    col.MinWidth:= b.Canvas.TextWidth(col.Text) + VST_COLUMN_GLYPH_WIDTH_ADDITION;

  finally
    b.Free;
  end;
Wenn dann Deine Value Spaltenbreite kleiner ist als die col.MinWidth musst Du gar nichts berechnen/setzen.
Die obige Aussage repräsentiert meine persönliche Meinung.
Diese erhebt keinen Anspruch auf Objektivität oder Richtigkeit.

Geändert von taveuni ( 8. Mär 2023 um 10:28 Uhr)
  Mit Zitat antworten Zitat
freejay

Registriert seit: 26. Mai 2004
Ort: Nürnberg
269 Beiträge
 
Delphi 11 Alexandria
 
#5

AW: VirtualTreeview als Grid optimale Spaltenbreite berechnen

  Alt 8. Mär 2023, 11:01
Also ich mache das bei StringGrids mit sehr vielen Zeilen so, dass ich die Breite der Spalten beim Zeichnen berechne: Ist die Spalte zu schmal für den neu gezeichneten Wert,
dann vergrößere ich sie in diesem Moment. Das bewirkt zwar, dass die Spalten beim Scrollen oft breiter werden. Der Vorteil ist aber, dass das automatische Berechnen der Spaltenbreiten praktisch sofort passiert und keine messbare Zeit nach dem Füllen der Tabelle (oder bei Dir: eines Trees) dafür verbraten wird. Ist aber sicher nicht jedermanns Sache.
[Delphi 11.3.1 Enterprise; Win10/11; MySQL; VCL]
  Mit Zitat antworten Zitat
Antwort Antwort


Forumregeln

Es ist dir nicht erlaubt, neue Themen zu verfassen.
Es ist dir nicht erlaubt, auf Beiträge zu antworten.
Es ist dir nicht erlaubt, Anhänge hochzuladen.
Es ist dir nicht erlaubt, deine Beiträge zu bearbeiten.

BB-Code ist an.
Smileys sind an.
[IMG] Code ist an.
HTML-Code ist aus.
Trackbacks are an
Pingbacks are an
Refbacks are aus

Gehe zu:

Impressum · AGB · Datenschutz · Nach oben
Alle Zeitangaben in WEZ +1. Es ist jetzt 16:19 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