使用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
相关产品推荐
相关产品推荐

