0

我动态地将帧填充到流面板中(作为水平方向的 VCL Metropolis 应用程序的一部分)。我需要调整每个组的流面板的大小以水平适应其所有项目。我有一个非常简单的公式有时可以解决问题,但并非总是如此-特别是​​在添加奇数个项目时。流面板FlowStyle设置为fsTopBottomLeftRight并垂直适合 2 个框架。

例如,添加 7 个项目会自动检测正确的宽度(跨 4 个项目)。但是添加 5 个项目并不能检测到正确的宽度(假设是 3 个跨度,但最终会检测到 2 个跨度)。

如何使它正确计算每个组的宽度?

这是将项目填充到每个项目组中的过程(删除了一些不相关的内容):

procedure TSplitForm.LoadScreen;
const
  FRAME_WIDTH = 170;    //Width of each frame
  FRAME_HEIGHT = 250;   //Height of each frame
  FRAME_MARGIN = 30;    //Margin to right of each group
  FRAME_VERT_COUNT = 2; //Number of frames vertically stacked
var
  CurGroup: TFlowPanel; //Flow panel currently being populated
  procedure ResizeGroup(FP: TFlowPanel);
  var
    Count, CountHalf, NewWidth, I: Integer;
  begin
    //Resize the specific flow panel's width to fit all items
    Count:= FP.ComponentCount;
    NewWidth:= FRAME_WIDTH + FRAME_MARGIN;  //Default width if no items
    if Count > 0 then begin
      //THIS IS WHERE MY CALCULATIONS DO NOT WORK
      CountHalf:= Round(Count / FRAME_VERT_COUNT);
      NewWidth:= (CountHalf * FRAME_WIDTH) + FRAME_MARGIN;
    end;
    if FP.Parent.Width <> NewWidth then
      FP.Parent.Width:= NewWidth;
    //Resize main flow panel's width to fit all contained group panels
    //(automatically extends within scroll box to extend scrollbar)
    Count:= TFlowPanel(FP.Parent.Parent).ControlCount;
    NewWidth:= 0;
    for I := 0 to Count-1 do begin
      NewWidth:= NewWidth + FP.Parent.Parent.Controls[I].Width;
    end;
    NewWidth:= NewWidth + FRAME_MARGIN;
    if FP.Parent.Parent.Width <> NewWidth then
      FP.Parent.Parent.Width:= NewWidth;
  end;
  procedure Add(const Name, Title, Subtitle: String);
  var
    Frame: TfrmItemFrame;
  begin
    Frame:= AddItemFrame(CurGroup, Name); //Create panel, set parent and name
    Frame.OnClick:= ItemClick;
    Frame.Title:= Title;
    Frame.Subtitle:= Subtitle;
    ResizeGroup(CurGroup);
  end;
begin
  CurGroup:= fpMainGroup;
  Add('boxMainItem1', 'Item 1', 'This is item 1');
  Add('boxMainItem2', 'Item 2', 'This is item 2');
  Add('boxMainItem3', 'Item 3', 'This is item 3');
  Add('boxMainItem4', 'Item 4', 'This is item 4');
  Add('boxMainItem5', 'Item 5', 'This is item 5');

  CurGroup:= fpInventoryGroup;
  Add('boxInventItem1', 'Item 1', 'This is item 1');
  Add('boxInventItem2', 'Item 2', 'This is item 2');
  Add('boxInventItem3', 'Item 3', 'This is item 3');
  Add('boxInventItem4', 'Item 4', 'This is item 4');
  Add('boxInventItem5', 'Item 5', 'This is item 5');
  Add('boxInventItem6', 'Item 6', 'This is item 6');
  Add('boxInventItem7', 'Item 7', 'This is item 7');
end;

这是该代码生成的屏幕截图:

项目宽度截图

如您所见,第一组有 5 个项目隐藏了第 5 个项目,但第二组有 7 个项目显示所有 7 都很好。

父子关系的结构是这样的(有问题的流程面板加粗):

  • SplitForm:TSplitForm(主窗体)
    • ScrollBox2:TScrollBox(主流程面板的容器)
      • fpMain:TFlowPanel(所有组面板的容器)
        • pMainGroup:TPanel(流程面板和标题面板的容器)
          • fpMainGroup : TFlowPanel(项目框架的容器)
          • pMainGroupTitle:TPanel(组顶部的标题)
        • pInventoryGroup:TPanel(流程面板和标题面板的容器)
          • fpInventoryGroup : TFlowPanel(物品展示框的容器)
          • pInventoryGroupTitle:TPanel(组顶部的标题)
        • (更多组的其他面板)

我尝试使用每个流面板的AutoSize属性,但它不承认高度(2 上)并使事情变得更糟。我基本上只需要正确检测这些流面板中的总列数。

4

2 回答 2

3
Round(Count / FRAME_VERT_COUNT);

这里FRAME_VERT_COUNT2。你Count5表情什么时候变成

Rount(2.5);

默认舍入模式是银行家舍入,计算结果为2。表达式是Count什么时候7

Round(3.5); 

银行家四舍五入意味着这是4.

您可以按照 Sertac 的建议和使用ceil. 但是,我会完全避免使用浮点数。它只是不需要,并且作为一般规则,如果它是可行的,则总是首选整数算术。你的表达应该是

(Count + FRAME_VERT_COUNT - 1) div FRAME_VERT_COUNT
于 2014-11-23T22:46:50.850 回答
2

您不想要部分平铺,因此当您计算需要多少列时,您需要最接近(等于或更大)的整数。

在默认舍入模式下,Round(7/2)为“4”。没关系。然而Round(5/2)是'2'。那是因为

在默认舍入模式 (rmNearest) 下,如果 X 恰好在两个整数之间,则结果始终为偶数。

只有两行,四舍五入可能是一种解决方案(除法始终是一个整数或正好在两个整数之间的一个数字)。对于一般解决方案,最好使用Ceil.

于 2014-11-23T22:39:43.467 回答