(Delphi FMX)如何使用Canvas.FillText显示在Ellipse的中间?

时间:2016-07-13 19:41:08

标签: delphi canvas firemonkey

我想将椭圆中间的数字显示为画布上绘制的文本。坐标将存储(对于椭圆)在数据库内部,文本值将存储在数据库的另一部分中。

到目前为止我所做的是我一直在使用来自FMXExpress (Github)的示范项目(DrawApp),在那里我将一些程序从私人改为公共。这些过程包括StartDrawing(startP:TPointF),EndDrawing(startP:TPointF),DoDraw()这样我可以从外部Unit / Object使用这些函数。该对象使用这些函数与MouseUp / MouseDown协调,以及一些属性,包括用于区分绘图是否正在进行的fDrawing,以及正在使用的工具(fdEllipse)。

我的主窗体使用FormCreate中的以下代码来初始创建fdrawbox:= TMyPaintBox.Create(Rectangle1); Rectangle1位于图像的顶部,图像表示显示身体部位的网格,并且能够在图像顶部绘制圆圈。我发现创建文本或椭圆并不难,但是为了创建带有标识符的多个圆来区分圆圈,正如我所提到的,我想要一个数字来显示哪个圆圈是哪个。即使在将来,我也可能想要更改颜色以显示要集中注意的圆圈。

demonstration for mypaintbox http://www.abatepain.com/abate/OHlbF.jpg

所以下面的代码(Delphi FMX)显示了使用TRectangle作为其父级来创建drawapp。

with fdrawbox do begin
  Parent := Rectangle1;
  Visible := True;
  ForegroundColor := TAlphaColor($FF000000); //
  BackgroundColor := TAlphaColor($00000000); //

  FuncDraw := TFunctionDraw.fdEllipse; //fdrawbox.fDrawing := True;
  StartDrawing(PointF(100, 100));
  EndDrawing(PointF(200, 200));
  FuncDraw := TFunctionDraw.fdNone;

  OnPaint := PaintBox1Paint;
end;

使用最后几行创建圆圈,但为了利用FillText,我需要使用我创建的OnPaint函数,代码看起来像这样。我相信DrawApp在内部处理OnPaint函数,但它如何处理它仍然是未知的。但是,为了打印" Hello Text !!"

,它永远不是必需品
procedure TMainForm.PaintBox1Paint(Sender: TObject; Canvas: TCanvas);
begin
  with Canvas do begin
    BeginScene();
    //Clear(cbbg.Color);
    Font.Style := [];
    Font.Size := 12;
    Fill.Color := TAlphaColors.Red;
    FillText(TRectF.Create(0, 0, 300, 295), 'Hello Text!!', false, 100, [], TTextAlign.Center, TTextAlign.Center); //TFillTextFlag.RightToLeft
    EndScene;
  end;
  Application.ProcessMessages;
end;

有人可以举例说明如何处理这个问题(可能在一个函数内部),我可以打印多个圆圈,然后跟随相关的文字吗?我相信前面的例子,我可以自己做,但我必须手动输入PointF(圆圈)和TRectF文本,他们都使用不同的值作为坐标。

1 个答案:

答案 0 :(得分:0)

正如您所指出的,TMyPaintBox类不支持文本呈现,也不支持常用于文本输出的属性,如字体或颜色等。但您可以通过在私有部分中定义字段来自行添加这些属性以及在公共部分中获取/设置值的属性。

在下文中,我假设添加了具有相应属性ftextout ffontsizeffontcolor的字段TextOutFontSizeFontColor

要添加以与绘制其他元素类型相似的方式呈现文本的功能,请将fdText添加为TFunctionDraw的新枚举。

  TFunctionDraw=(fdNone,fdPen,fdLine,fdRectangle,fdEllipse,fdFillBgr,fdBitmapStamp,fdPolyLine, fdText);

然后在TMyPaintBox.DoDraw中为case ffdraw of添加一个新案例选项,例如:

with vCanvas do
begin
BeginScene();
case ffdraw of 
  //
  // other TFunctionDraw enums
  //
  TFunctionDraw.fdText: begin
    {Canvas.}Font.Size := ffonsize; // new field
    {Canvas.}Fill.Color := ffontcolor; // new field 
    {Canvas.}FillText(r, TextOut, False, 1, [],
      TTextAlign.Center, TTextAlign.Center);
  end;
end;

修改

Canvas中对TFunctionDraw.fdText的引用是多余的。删除已过时的参考文献。要使用的画布已在with语句中定义(添加到要显示的代码中)。哦,我讨厌那些with s!

值得注意的是,如果您只想显示带有文字的圆圈,而不是让用户在画布上绘图,那么您可以使用自己的组件更简单地实现它。

另外,请勿直接致电DoDraw。它由Paint调用,只要fdrawbox无效就会触发它。因此,当您想强制更新时,请调用invalidate

编辑结束

然后你可以像任何其他元素绘图一样实现文本渲染(使用你的代码模板):

with fdrawbox do begin
  Parent := Rectangle1;
  Visible := True;
  ForegroundColor := TAlphaColor($FF000000); //
  BackgroundColor := TAlphaColor($00000000); //

  FuncDraw := TFunctionDraw.fdEllipse; //fdrawbox.fDrawing := True;
  StartDrawing(PointF(100, 100));
  EndDrawing(PointF(200, 200));

  FuncDraw := TFunctionDraw.fdText;
  FontSize := 12; // set new property
  FontColor := TAlphaColorRec.Red; // set new property
  TextOut := 'Hello text!';
  StartDrawing(PointF(100, 100));
  EndDrawing(PointF(200, 200));

  FuncDraw := TFunctionDraw.fdNone;

  invalidate;
  // OnPaint := PaintBox1Paint; // no need for this
end;