Mam około 30 różnych napisów. Każdy napis jest w innym Labelu. Teksty są też w tablicy. O ile ilość znaków łatwo byłoby sprawdzić poprzez for i if. Jednak Labele mają przypisaną czcionkę i rozmiar, a ja chce porównać ich szerokość, a nie długość. Co oczywiste każdy Label ma inną nazwę, więc użycie for chyba nie będzie możliwe. Konkretnie potrzebuję znaleźć największą szerokość. Czy da się to zrobić w jakiś sposób, a nie pisać 30 ifów?
Weź zrób tablicę w klasie arr:array[0..29]of TLabel
;
Wszystkie te Label'e postaw na Box:TPanel;
W konstruktorze zainicjalizuj:
K:=0;
for I:=0 i<Box.ControlCount-1 do if Box.Controls[I] is TLabel then begin arr[K]:=TLabel(Box.Controls[I]); Inc(K); end;
Dalej możesz używać tablicę arr
Jeszcze nie sprawdziłem tego, ale tak po przeczytaniu wydaje mi się że tu problem będzie taki, że Labele będą rozróżniane indeksem. I tak na prawdę można się pogubić w tym. A ja bym chciał, żeby każdy miał charakterystyczną nazwę. Najłatwiej by było gdyby istniała jakaś funkcja, w której można by było podać wszystkie argumenty a zwracałaby wartość największej. Ostatecznie sam mogę napisać taką funkcję z użyciem tych 30 ifów.
Nadal będziesz mógł używać te Label'e poprzez nadane nazwy.
@dani17 - jeżeli każda z etykiet ma ustawioną właściwość AutoSize
na True, to szerokość komponentu jest taka sama, jak i szerokość jego tekstu; Jeśli natomiast komponenty nie dostosowują swojego rozmiaru automatycznie, to możesz skorzystać z metody Canvas.TextWidth
; Dzięki temu rodzaj i styl fontu w różnych etykietach nie będzie stanowił problemu;
Jeżeli wszytkie etykiety mają wspólnego rodzica (leżą na tym samym komponencie dziedziczącym z klasy TWinControl
lub leżą bezpośrednio na formularzu), możesz skorzystać z pętli For i właściwości Controls
oraz ControlsCount
do iterowania po etykietach, a także operatora Is do sprawdzania klasy komponentu;
Przykład:
procedure TForm1.btnFindMaxWidthClick(Sender: TObject);
var
lblToken: TLabel;
intToken: Int32;
intMaxWidth: Int32 = 0;
begin
for intToken := 0 to Form1.ComponentCount - 1 do
if Form1.Components[intToken] is TLabel then
begin
lblToken := Form1.Components[intToken];
intMaxWidth := Max(intMaxWidth, lblToken.Canvas.TextWidth(lblToken.Caption));
end;
Application.MessageBox(PChar('Max: ' + IntToStr(intMaxWidth)), 'Label Widths', MB_ICONINFORMATION);
end;
Ewentualnie odpuść sobie funkcję Max i zastąp ją zwykłym warunkiem (choć ta funkcja sama w sobie ma zwykły warunek, tyle że upraszcza i skraca zapis).
furious programming napisał(a):
@dani17 - jeżeli każda z etykiet ma ustawioną właściwość
AutoSize
na True, to szerokość komponentu jest taka sama, jak i szerokość jego tekstu; Jeśli natomiast komponenty nie dostosowują swojego rozmiaru automatycznie, to możesz skorzystać z metodyCanvas.TextWidth
; Dzięki temu rodzaj i styl fontu w różnych etykietach nie będzie stanowił problemu;
Tak mam ustawione Autosize, ale chodzi mi o trochę coś innego. Ale mogę się mylić. Po prostu wydaje mi się, że w zależności od rodzaju czcionki szerokość liter może być różna. To znaczy, że w jednej czcionce "ł" będzie szersze od "a', a w innej nie. Dlatego zależy mi na tym, aby sprawdzić który z tych napisów będzie najszerszy przy wybranej czcionce. Zrobiłem na razie porównań przez if z użyciem Label.Canvas.TextWidth i działa to tak jak chciałem.
@dani17 - przecież napisałem Ci wyraźnie, że metoda Canvas.TextWidth
mierzy fizyczną szerokość tekstu w pikselach, biorąc pod uwagę aktualnie ustawione preferencje fontu w danej kanwie; A że każdy komponent ma swoją kanwę, to dla każdej etykiety mierzenie odbywa się z osobna i styl fontu nie ma znaczenia;
Zrobiłem na razie porównań przez if z użyciem Label.Canvas.TextWidth i działa to tak jak chciałem.
No to dobrze, że działa według Twoich oczekiwań; A co do zastosowania instrukcji If - jest ona konieczna, jeśli nie korzysta się z funkcji Max (plus dodatkowa zmienna, żeby nie liczyć szerokości tekstu dwa razy);
Jeśli wszystko już gra to zakończ wątek.