根据内容计算流量面板宽度

时间:2014-11-23 20:11:26

标签: delphi resize flowpanel

我动态地将帧填充到流动面板中(作为水平导向的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;

这是该代码产生的截图:

Item width screenshot

正如你所看到的,第一组有5个项目隐藏了第5个项目,但第二个组有7个项目显示所有7个项目就好了。

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

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

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

2 个答案:

答案 0 :(得分:3)

Round(Count / FRAME_VERT_COUNT);

此处FRAME_VERT_COUNT2。当Count5时,您的表达式变为

Rount(2.5);

默认的舍入模式是银行家四舍五入,评估为2。当Count7时,表达式为

Round(3.5); 

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

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

(Count + FRAME_VERT_COUNT - 1) div FRAME_VERT_COUNT

答案 1 :(得分:2)

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

在默认的舍入模式中,Round(7/2)为&#39; 4&#39;。没关系。但是Round(5/2)是&#39; 2&#39;。 That's because

  

使用默认的舍入模式(rmNearest),如果X恰好是中途   在两个整数之间,结果总是偶数。

只有两行,向上舍入可以是一个解决方案(除法总是一个整数或两个整数之间的数字)。对于一般解决方案,最好使用Ceil