You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用FMX中TPaintBox绘制规范美国国旗的技术求助

修正TPaintBox绘制美国国旗的星星问题

先明确美国国旗的精准参数(必须遵循才能画对)

  • 整体比例:高:宽 = 10:19
  • 左上角蓝色 canton(星区):高为7个条纹高度,宽为13个条纹宽度(对应13条红白横纹)
  • 星星规则:共50颗,分9行排列——奇数行(第1、3、5、7、9行)各5颗,偶数行(第2、4、6、8行)各6颗;星星中心的水平间距为 canton宽度/12,垂直间距为 canton高度/8;五角星的外接圆直径为条纹高度的0.616倍

核心修正代码

1. 五角星绘制函数

在窗体类中添加这个辅助函数,用于绘制标准五角星:

procedure DrawStar(Canvas: TCanvas; CenterX, CenterY, Radius: Integer);
var
  Points: array[0..4] of TPoint;
  Angle: Double;
  i: Integer;
begin
  Canvas.Brush.Color := clWhite;
  Canvas.Pen.Color := clWhite;
  // 计算五角星的五个顶点
  for i := 0 to 4 do
  begin
    Angle := (i * 144 - 90) * Pi / 180; // 144°间隔,初始偏移90°让顶点朝上
    Points[i].X := CenterX + Round(Radius * Cos(Angle));
    Points[i].Y := CenterY + Round(Radius * Sin(Angle));
  end;
  Canvas.Polygon(Points);
end;

2. 完整的PaintBox1Paint事件修正

替换你现有的Paint事件代码,以下是精准适配的版本:

procedure TForm1.PaintBox1Paint(Sender: TObject);
var
  FlagHeight, FlagWidth: Integer;
  StripeHeight, CantonWidth, CantonHeight: Integer;
  StarRadius, StarHSpacing, StarVSpacing: Integer;
  Row, Col: Integer;
  StarX, StarY: Integer;
  i: Integer;
begin
  // 按标准比例计算尺寸,以PaintBox高度为基准,避免变形
  FlagHeight := PaintBox1.Height;
  FlagWidth := Round(FlagHeight * 19 / 10);
  
  // 确保PaintBox宽度足够,否则按宽度为基准
  if FlagWidth > PaintBox1.Width then
  begin
    FlagWidth := PaintBox1.Width;
    FlagHeight := Round(FlagWidth * 10 / 19);
  end;

  // 计算条纹高度和星区尺寸
  StripeHeight := Round(FlagHeight / 13);
  CantonHeight := StripeHeight * 7;
  CantonWidth := Round(FlagWidth * 13 / 19);

  // 计算星星参数
  StarRadius := Round(StripeHeight * 0.616 / 2); // 外接圆直径是条纹高度的0.616倍,取半径
  StarHSpacing := CantonWidth div 12; // 水平12个间隔(13列位置)
  StarVSpacing := CantonHeight div 8; // 垂直8个间隔(9行位置)

  // 绘制红白条纹
  Canvas.Brush.Style := bsSolid;
  for i := 0 to 12 do
  begin
    if Odd(i) then
      Canvas.Brush.Color := clRed
    else
      Canvas.Brush.Color := clWhite;
    Canvas.FillRect(Rect(0, i * StripeHeight, FlagWidth, (i+1)*StripeHeight));
  end;

  // 绘制蓝色星区背景
  Canvas.Brush.Color := $000080; // 标准美国国旗蓝色
  Canvas.FillRect(Rect(0, 0, CantonWidth, CantonHeight));

  // 绘制星星:奇数行5颗,偶数行6颗
  for Row := 0 to 8 do
  begin
    if Odd(Row) then // 偶数行(Row从0开始,奇数索引对应第2、4...行)
    begin
      for Col := 0 to 5 do
      begin
        StarX := StarHSpacing div 2 + Col * StarHSpacing;
        StarY := StarVSpacing div 2 + Row * StarVSpacing;
        DrawStar(Canvas, StarX, StarY, StarRadius);
      end;
    end
    else // 奇数行(Row偶数索引对应第1、3...行)
    begin
      for Col := 0 to 4 do
      begin
        StarX := StarHSpacing + Col * StarHSpacing;
        StarY := StarVSpacing div 2 + Row * StarVSpacing;
        DrawStar(Canvas, StarX, StarY, StarRadius);
      end;
    end;
  end;
end;

关键修正点说明

  • 强制遵循国旗比例,避免拉伸变形导致星星错位
  • 五角星顶点计算采用标准144°间隔,确保形状正确
  • 星星位置计算严格按照星区的间距规则,奇偶行的水平偏移处理正确
  • 用$000080作为标准国旗蓝色(而非随便选的蓝色)

额外优化建议

  • 在PaintBox的OnResize事件中调用PaintBox1.Invalidate,确保窗口大小变化时自动重绘
  • 如果需要适配不同大小的PaintBox,保持比例的逻辑已经包含在代码中

内容的提问来源于stack exchange,提问作者user31362432

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.11 19:12:32