![]() |
VirtualTreeview als Grid optimale Spaltenbreite berechnen
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:
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 |
AW: VirtualTreeview als Grid optimale Spaltenbreite berechnen
Ich habe den VST in Delphi leider nie installiert aber in Lazarus.
Dort gibt es "VST.Header.AutoFitColumns()" als Methode.
Delphi-Quellcode:
Meintest Du sowas?
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; |
AW: VirtualTreeview als Grid optimale Spaltenbreite berechnen
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. |
AW: VirtualTreeview als Grid optimale Spaltenbreite berechnen
Zitat:
Delphi-Quellcode:
Wenn dann Deine Value Spaltenbreite kleiner ist als die col.MinWidth musst Du gar nichts berechnen/setzen.
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; |
AW: VirtualTreeview als Grid optimale Spaltenbreite berechnen
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. |
Alle Zeitangaben in WEZ +1. Es ist jetzt 01:02 Uhr. |
Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024-2025 by Thomas Breitkreuz