Delphi XE2 Firemonkey 的 Align 属性设置为 alScale 对坐标系有何影响?
Posted
技术标签:
【中文标题】Delphi XE2 Firemonkey 的 Align 属性设置为 alScale 对坐标系有何影响?【英文标题】:How does Delphi XE2 Firemonkey's Align property set to alScale affect the coordinate system? 【发布时间】:2012-08-26 20:58:40 【问题描述】:我正在查看 Firemonkey 的画布绘图功能,并在组件的 Align 属性设置为 alScale 时遇到了坐标系统问题。以下演示程序(FM HD 应用程序)说明了该问题。 编译并运行示例代码,画几行,然后更改表单的大小以开始奇怪。这些线条没有出现在预期的位置。
任何建议和解释将不胜感激!提前致谢。
主窗体(LineDrawFormUnit.pas):
unit LineDrawFormUnit;
interface
uses
System.SysUtils, System.Types, System.UITypes, System.Classes, System.Variants,
FMX.Types, FMX.Controls, FMX.Forms, FMX.Dialogs, FMX.Objects;
type
TLineDrawForm = class(TForm)
Image1: TImageControl;
Panel1: TPanel;
Label1: TLabel;
Label2: TLabel;
lX: TLabel;
lY: TLabel;
These event handlers are set in the IDE's object inspector
procedure Image1MouseDown(Sender: TObject; Button: TMouseButton; Shift: TShiftState; X, Y: Single);
procedure Image1MouseUp(Sender: TObject; Button: TMouseButton; Shift: TShiftState; X, Y: Single);
This event handler is set/unset with the MouseDown and MouseUp events to capture mouse moves when drawing
procedure ImageControl1MouseMove(Sender: TObject; Shift: TShiftState; X, Y: Single);
procedure FormCreate(Sender: TObject);
private
FSaveBitmap: TBitmap;
p1, p2: TPointF; Start and end points of lines to draw
end;
var
LineDrawForm: TLineDrawForm;
implementation
$R *.fmx
procedure TLineDrawForm.FormCreate(Sender: TObject);
begin
Image1.Bitmap.Create(Round(Image1.Width), Round(Image1.Height));
end;
procedure TLineDrawForm.Image1MouseDown(Sender: TObject; Button: TMouseButton; Shift: TShiftState; X,
Y: Single);
begin
p1.X := X;
p1.Y := Y;
lX.Text := FloatToStr(X);
lY.Text := FloatToStr(Y);
FSaveBitmap := TBitmap.Create(Image1.Bitmap.Width, Image1.Bitmap.Height);
FSaveBitmap.Assign(Image1.Bitmap); Save the current canvas as bitmap
Image1.OnMouseMove := ImageControl1MouseMove; Activate the MouseMove event handler
end;
procedure TLineDrawForm.ImageControl1MouseMove(Sender: TObject; Shift: TShiftState; X, Y: Single);
begin
p2.X := X;
p2.Y := Y;
lX.Text := FloatToStr(X);
lY.Text := FloatToStr(Y);
Image1.Bitmap.Assign(FSaveBitmap);
Image1.Bitmap.Canvas.BeginScene;
try
Image1.Bitmap.Canvas.Stroke.Color := claGray;
Image1.Bitmap.Canvas.StrokeThickness := 0.5;
Image1.Bitmap.Canvas.DrawLine(p1, p2, 1.0);
finally
Image1.Bitmap.Canvas.EndScene;
Image1.Bitmap.BitmapChanged;
end;
end;
procedure TLineDrawForm.Image1MouseUp(Sender: TObject; Button: TMouseButton; Shift: TShiftState; X,
Y: Single);
begin
p2.X := X;
p2.Y := Y;
lX.Text := FloatToStr(X);
lY.Text := FloatToStr(Y);
Image1.Bitmap.Canvas.BeginScene;
try
Image1.Bitmap.Canvas.Stroke.Color := claBlack;
Image1.Bitmap.Canvas.StrokeThickness := 2;
Image1.Bitmap.Canvas.DrawLine(P1, P2, 1.0);
finally
Image1.Bitmap.Canvas.EndScene;
Image1.Bitmap.BitmapChanged;
end;
(Sender as TControl).OnMouseMove := nil;
if FSaveBitmap <> nil then
FSaveBitmap.Free;
end;
end.
FMX 文件(LineDrawFormUnit.fmx):
object LineDrawForm: TLineDrawForm
Left = 0
Top = 0
Caption = 'Polygon Form'
ClientHeight = 513
ClientWidth = 650
Visible = False
OnCreate = FormCreate
StyleLookup = 'backgroundstyle'
object Image1: TImageControl
Align = alScale
Position.Point = '(18,21)'
Width = 620.000000000000000000
Height = 452.000000000000000000
OnMouseDown = Image1MouseDown
OnMouseUp = Image1MouseUp
TabOrder = 0
end
object Panel1: TPanel
Align = alBottom
Position.Point = '(0,480)'
Width = 650.000000000000000000
Height = 33.000000000000000000
TabOrder = 2
object Label1: TLabel
Position.Point = '(16,8)'
Width = 25.000000000000000000
Height = 15.000000000000000000
TabOrder = 1
Text = 'X:'
end
object Label2: TLabel
Position.Point = '(384,8)'
Width = 25.000000000000000000
Height = 15.000000000000000000
TabOrder = 2
Text = 'Y:'
end
object lX: TLabel
Position.Point = '(32,8)'
Width = 313.000000000000000000
Height = 15.000000000000000000
TabOrder = 3
Text = '0'
end
object lY: TLabel
Position.Point = '(424,8)'
Width = 209.000000000000000000
Height = 15.000000000000000000
TabOrder = 4
Text = '0'
end
end
end
【问题讨论】:
P.S.我最初忘记在接口 Uses 子句中删除未使用的 PolygonUnit,现在已更正。 Image1.Bitmap 随表格放大时,Image1.Bitmap 未按比例放大。但是,当 Image1 与窗体一起缩小时,它的大小会减小,而当窗体展开时,它会再次扩大到原始大小。为表单设置 OnResize 处理程序允许调整 Image1.Bitmap 的大小以匹配其容器,但它被清除。当窗体的大小缩小和扩大时,位图会缩小并恢复到其原始大小。必须有一种无损方式来调整 TBitmap 的大小而不清除其内容。否则,将不得不求助于使用 TBitmap.ScanLine 函数。 P.S.放大位图会使它变得粗糙,因此位图缩小并返回到其原始大小而不是更大是有意义的。还需要弄清楚框架内部是如何实现的。 我认为这与Align
属性没有任何关系(顺便说一下,它也可以与alClient
重现)。问题是由于图像控件的大小已调整但其位图未调整,因此它会缩放。创建 FSaveBitmap 时,您应该使用图像控件的大小创建它,而不是其内部位图(否则您不会反映控件的更改大小并导致缩放)。
谢谢 TOndrej。我会试试你的建议。
【参考方案1】:
align 属性影响 TShapes 后代、TControl 等,但不影响位图的内容。
您似乎在 TBitmap 上缓冲了一些自定义绘图,然后将其分配给控件。 FMX 将无法重新对齐自定义图形,因为它们没有封装在可对齐的类中(只是一些像素)。
您可以在调整控件大小时重新绘制“缓冲区”并将其重新分配给其“主机”以根据您的意愿调整绘图。或者也许不要释放“缓冲图纸”并在调整表单大小时对其进行转换/重新分配。
但是,一种更好的方法是使用形状系统,它与 FMX HD 的预期使用方式相匹配,对齐将是自动的。 所以不要画线,而是在父对象内部创建一个 TLine 并根据父控件分层这条新线的对齐方式。
【讨论】:
感谢您的回复。我现在正在使用使用 TPath 对象的类似方法。它让生活变得更加轻松。此外,MouseDown 事件已经非常有效地检查多边形中的点。为我找到的路径对象创建数据的最简单方法是在 Illustrator/InkScape 中绘制形状,以 SVG 格式保存文件并使用文本编辑器从文件中提取相关路径信息。我真的希望 FireMonkey 有更好的文档。以上是关于Delphi XE2 Firemonkey 的 Align 属性设置为 alScale 对坐标系有何影响?的主要内容,如果未能解决你的问题,请参考以下文章
如何在Delphi FireMonkey中发送iOS的推送通知
Delphi xe7 FireMonkey / Mobile (Android, iOS)生成 QR Code完整实例
如何改变delphi xe2编程环境下所显示的源代码的字体大小