Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > .NET для новичков > Динамическая высота Label


Автор: Skiminok 9.5.2008, 18:17
Здравствуйте. Есть такой вот вопрос. Лично мне он кажется ламерским донельзя, но выхода найти не могу...
Имеется Label. От него требуется следующее:
  • фиксированная ширина
  • перенос по словам
  • изменение высоты в зависимости от текста
Пункт 1 банален.
Пункт 2 достигается только установкой AutoSize в false.
А вот что теперь делать с пунктом 3, если нельзя ресайзить автоматически...
Пробовал следующее:
Код

using (System.Drawing.Graphics g = lblMainPage.CreateGraphics())
{
  lblMainPage.Height = (int)g.MeasureString(lblMainPage.Text, lblMainPage.Font, lblMainPage.Width).Height;
}

Ресайзит, но на перенос строк не реагирует. То есть, если в Label'e 3 строки, причем вторая из них превышает ширину label'a, то высота установится именно в 3 строки, вследствие чего строчку №3 увидеть будет невозможно.
Замена Graphics.MeasureString на TextRenderer.MeasureText не помогает.
Что делать, не представляю. Уже с ног сбился. Буду очень благодарен за помощь.

Автор: mr.DUDA 9.5.2008, 19:57
Решается выставлением AutoSize=false, фиксированным размером по горизонтали и большим размером по вертикали (заведомо бОльшим чем размер Label). Сам текст будет автоматом переноситься на новую строку, а за счёт того что фон прозрачный - будет впечатление что это вертикальный размер растёт автоматически.

Автор: Skiminok 9.5.2008, 20:08
Цитата(mr.DUDA @  9.5.2008,  19:57 Найти цитируемый пост)
Решается выставлением AutoSize=false, фиксированным размером по горизонтали и большим размером по вертикали (заведомо бОльшим чем размер Label). Сам текст будет автоматом переноситься на новую строку, а за счёт того что фон прозрачный - будет впечатление что это вертикальный размер растёт автоматически.
Это очевидный способsmile Только я никогда не знаю размер текста, который будет отображаться на Label'e - он определяется в run-time. Да и контролы внизу не хотелось бы перекрывать...
Наверняка же существует не читерское решение smile

Автор: mr.DUDA 9.5.2008, 20:35
Skiminok, так по-любому контролы будут перекрыты в худшем случае (если высота текста слишком велика), не так ли? А фон у лейбла прозрачный, в чём проблема?

Автор: Skiminok 14.5.2008, 23:04
Проблема в том, что я в проге выстраиваю в столбик серию компонентов на форме в run-time.
И для того чтобы поместить новый компонент в правильное место, мне нужно знать точные координаты, где заканчивается "осмысленная", а не "техническая" часть верхнего.
(попытался объяснить на пальцах, неформальноsmile)

Автор: sawtooth 3.8.2010, 21:48
Столкнулся с аналогичной проблемой. Решение нашлось. Возможно, ещё пригодится:
Код

Label label1 = new Label();
label1.Text = "текст";
label1.Width = статическая_ширина;
label1.Height = label1.GetPreferredSize(new Size(label1.Width,0)).Height;

Автор: boojum 29.2.2012, 07:56
Цитата(Skiminok @ 9.5.2008,  18:17)
Здравствуйте. Есть такой вот вопрос. Лично мне он кажется ламерским донельзя, но выхода найти не могу...
Имеется Label. От него требуется следующее:

  • фиксированная ширина
  • перенос по словам
  • изменение высоты в зависимости от текста
Пункт 1 банален.
Пункт 2 достигается только установкой AutoSize в false.
А вот что теперь делать с пунктом 3, если нельзя ресайзить автоматически...

Проблемы начались с того, что вы посчитали пункт 1  банальным:)
Т.е. с ходу решили ставить AutoSize:=false; WordWrap:=true;
А ведь можно было бы немного подумать и тогда....

(На net  не пишу, но в дельфе то же самое, так что сообразите, кому нужно).

Код

//Фиксируем ширину лейбла
Label1.Constraints.MaxWidth:=YourWidth;
Label1.Constraints.MinWidth:=YourWidth;

//А теперь автосайзим сколько угодно
Label1.AutoSize:=TRUE;
Label1.WordWrap:=true;


Ширина будет оставаться фиксированной (а куда ей деваться?), высота будет меняться при переносе по словам.

Более того, если сам лейбл автосайзить не можете (например, у него Align=alClient), а в рантайме хотите менять размеры его родителя (Parent), скажем, панели на которой он лежит, то нетрудно посчитать высоту текста с помощью невидимого лейбла(точнее, вообще безхозного лейбла, точнее лейбла-сироты (Parent=nil)):

Код

function TFrame1.CalcLblHeight(_lbl: TLabel): Integer;
begin
  Result :=0;
  if not Assigned(_lbl) then Exit;
  fLbl.Font:=_lbl.Font;
  fLbl.Constraints.MaxWidth:=_lbl.Width;
  fLbl.Constraints.MinWidth:=_lbl.Width;
  fLbl.Caption:=_Lbl.Caption;
  Result:=fLbl.Height;
end;



Параметр _lbl - лейбл высоту текста которого хотите измерить, при существующей у него ширине и шрифте.
fLbl - экземпляр TLabel, который создается и уничтожается соответственно в конструкторе и деструкторе Вашей формы/фрейма/класса или при инизализации/финализации модуля:

Код

constructor TFrame1.Create(AOwner: TComponent);
begin
  inherited Create(AOwner);
  //Parent остается nil - таким образом, высота даже теоретически не может быть ограничена размерами родителя (как будет в случае использования для измерения паразитного невидимого лейбла на форме )
  if not Assigned(fLbl) then fLbl := TLabel.Create(nil);
  fLbl.AutoSize:=true;
  fLbl.WordWrap:=true;
end;

destructor TFrame1.Destroy;
begin
  if Assigned(fLbl) then FreeAndNil(fLbl);
  inherited Destroy;
end;



Ну и естественно, fLbl нужно объявить как TLabel. Скажем, в private секции TFrame1.

ПРЕДУПРЕЖДЕНИЕ: все отлично работает до тех пор, пока ширина слов текста меньше или равна ширине лейбла. Если она больше - поведение лейбла  вообще странно-непонятное, разное, но палюбому неадекватное.  Поэтому о переносе или разрыве слишком длинных слов нужно заботиться отдельно

 
 

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)