Delphi FMX TCheckbox/TRadiobutton Autosize

痞子三分冷 提交于 2021-02-10 06:46:26

问题


I want dynamically created Checkboxes and Radiobuttons (in FMX, not VCL) with a fixed Width to change their Heigth based on their containing text. My Checkboxes and Radiobuttons have WordWrap enabled. So I want to get something like the TLabel does, when AutoSize and WordWrap are enabled.

I've already managed to get close to this:

procedure TFMenu.Button1Click(Sender: TObject);
var
  ctr: Integer;
  hostingComponent: TComponent;
begin
  hostingComponent := Form1; { in my case a Frame or Panel or sth. }
  for ctr := 0 to pred(hostingComponent.ComponentCount) do
  begin
    if hostingComponent.Components[ctr] is TRadioButton { or TCheckBox } then
    begin
      with (hostingComponent.Components[ctr] as TRadioButton) do
      begin
        Height := 0; { if text or text Width changes this is useful }
        while (Height) * (Width - 32)
        <=
        (Canvas.TextHeight(Text) * 1.25 ) * Canvas.TextWidth(Text) do
        begin
          Height := Height + 1;
        end;
      end;
    end;
  end;
end;

This works something like acceptable for texts between 20 and 150 Characters, however I know this is very wrong and I don't know, what I am missing here. Multiplying Canvas.TextHeight by 1.25 made the text look okay for the length mentioned above, but I don't know why. Width - 32 is because of the size of the image of the checkbox/radiobutton, which is not the text I want to handle. (I guessed 32 would be right, it could differ in reality)

So my question is how to change the Heigth of those Components based on the containing text.

Also: How can I change my code to work as expected. The maths behind it (except for the multiplication by the guessed value 1.25) should be correct, but the areas I use seem to be wrong as the area of the Checkbox/Radiobutton does not entirely contain text but end with some free space as the text is not block, but simply left-bounded, but I'm not sure, whether this is important or how to deal with that.


回答1:


You can use the Canvas.MeasureText() method to measure the text and then set the size of the TRadioButton.

For example:

procedure TForm22.Button1Click(Sender: TObject);
var
  r: TRectF;
begin
  rb1:= TRadioButton.Create(self);
  rb1.Parent := self;
  rb1.Position.X := 100;
  rb1.Position.Y := 8;
  rb1.Size.Height := 17;
  rb1.Size.Width := 260;

  rb1.StyledSettings := [];
  rb1.TextSettings.Font.Size := 18;
  rb1.TextSettings.WordWrap := True;
  rb1.Canvas.Font.Size := rb1.TextSettings.Font.Size;

  r := RectF(0, 0, rb1.Size.Width-24, 10000);
  rb1.Canvas.MeasureText(r, s, True, [], TTextAlign.Leading, TTextAlign.Leading);

  rb1.Size.Height := r.Bottom;
  rb1.Text := s;
end;

The ARect (var) parameter specifies the bounding rectangle of the text. The function fits the text inside the rectangle (if possible). By specifying the width limit, but a large enough height, the function obeys the width and measures the required height (which is modified in the returned TRectF).

In my example I subtracted 24 from the TRadioButton width to compensate for the actual radiobutton. The default style data indicates 21 would be sufficient, but I added 3 to be on the safe side in the calculation. With other styles this number might be different. See Position.Xproperty of the text member in style data for TRadioButton/TCheckBox.

As you see in my code example, there was no need to adjust anything with the 1.25 factor you used. My system is at 100% DPI, if your is at 125%, it could explain what you experienced. If that is still a problem, you need to check the system that you program is running on and compensate as needed.

Finally a picture of a form with 2 radio buttons of width=260 and width=400.



来源:https://stackoverflow.com/questions/47492184/delphi-fmx-tcheckbox-tradiobutton-autosize

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!