首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >FireMonkey PenMode等效项- DrawLine

FireMonkey PenMode等效项- DrawLine
EN

Stack Overflow用户
提问于 2012-04-24 11:22:31
回答 2查看 4.3K关注 0票数 2

我尝试使用FireMonkey只是为了测试一些东西。其中之一是在画布上实现“非常简单”的绘图。例如线条、矩形等。

第一个问题是,有没有一个等同于VCL for FireMonkey的graphex演示?

另外,出于练习的目的,我将尝试在FireMonkey中复制该演示,并在前面绘制线条。我可以让线条画工作,就像我在线条画周围移动鼠标时所期望的那样。不幸的是,我不能让它自动删除在鼠标所在的前一点绘制的旧线。这似乎是由TPen属性的TPenMode属性负责的,据我所知,它是FireMonkey中的一个TStroke属性。即在绘制(移动鼠标)时将该属性设置为pmXor,然后在完成时将其设置为pmCopy。

我该如何用FireMonkey做类似的事情呢?

下面是在TImage的MouseMove事件期间调用的例程:

代码语言:javascript
复制
  FDrawSurface.Bitmap.Canvas.BeginScene;
  try
    case FShapeToDraw of
      doLine:
      begin
        FDrawSurface.Bitmap.Canvas.DrawLine(PointF(TopLeft.X, TopLeft.Y), PointF(BottomRight.X, BottomRight.Y), 100);
      end;

    end;
  finally
    FDrawSurface.Bitmap.Canvas.EndScene;
    FDrawSurface.Bitmap.BitmapChanged;
  end;

FDrawSurface是一个TImage。TopLeft是一个TPoint,它包含在TImaeg的OnMouseDown事件中捕获的鼠标所在位置的X和Y坐标,BottomRight是OnMouseMove事件的当前X和Y坐标。

因此,每次我移动鼠标时,我的图像上都会出现“附加”线条。

谢谢

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2012-04-25 05:59:37

AFAIK,FMX没有这样的模式...此外,您在画布上绘制的内容并未真正保存(如果您知道如何直接保存它,请在评论中向我解释):如果您将窗体移出桌面,并将其带回,画布将被清理……

因此,要实现graphex演示,您必须使用其他技术对其进行编码。

例如,使用TBitmap来存储真实的“图像”,并且只使用画布进行“预览”……

代码语言:javascript
复制
unit main;

interface

uses
  System.SysUtils, System.Types, System.UITypes, System.Classes, System.Variants,
  FMX.Types, FMX.Controls, FMX.Forms, FMX.Dialogs, FMX.Objects;

type
  TfrmMain = class(TForm)
    recBoard: TRectangle;
    btnCopy: TButton;
    Image1: TImage;
    procedure recBoardMouseDown(Sender: TObject; Button: TMouseButton; Shift: TShiftState; X, Y: Single);
    procedure recBoardMouseMove(Sender: TObject; Shift: TShiftState; X, Y: Single);
    procedure recBoardMouseUp(Sender: TObject; Button: TMouseButton; Shift: TShiftState; X, Y: Single);
    procedure recBoardMouseInOut(Sender: TObject);
    procedure FormCreate(Sender: TObject);
    procedure btnCopyClick(Sender: TObject);
    procedure FormDestroy(Sender: TObject);
  private
    { Private declarations }
    bmp: TBitmap;
    pFrom, pTo: TPointF;
  public
    { Public declarations }
  end;

var
  frmMain: TfrmMain;

implementation

{$R *.fmx}

procedure TfrmMain.btnCopyClick(Sender: TObject);
begin
  Image1.Bitmap.Assign(bmp);
end;

procedure TfrmMain.FormCreate(Sender: TObject);
begin
  pFrom := PointF(-1, -1);
  bmp := TBitmap.Create(Round(recBoard.Width), Round(recBoard.Height));
end;

procedure TfrmMain.FormDestroy(Sender: TObject);
begin
  bmp.Free;
end;

procedure TfrmMain.recBoardMouseDown(Sender: TObject; Button: TMouseButton; Shift: TShiftState; X, Y: Single);
begin
  if Button = TMouseButton.mbLeft then
  begin
    pFrom := PointF(X, Y);
    pTo   := PointF(X, Y);
  end;
end;

procedure TfrmMain.recBoardMouseInOut(Sender: TObject);
begin
  pFrom := PointF(-1, -1);
end;

procedure TfrmMain.recBoardMouseMove(Sender: TObject; Shift: TShiftState; X, Y: Single);
begin
  if ((pFrom.X <> -1) and (pFrom.X <> -1)) then
  with recBoard.Canvas do
  begin
    BeginScene;
    if ssLeft in Shift then
    begin
      FillRect(RectF(0, 0, bmp.Width, bmp.Height), 0, 0, [], 255);
      DrawBitmap(bmp, RectF(0, 0, bmp.Width, bmp.Height), RectF(0, 0, bmp.Width, bmp.Height), 255);
      Stroke.Color := claBlue;
      pTo := PointF(X, Y);
      DrawEllipse(RectF(pFrom.X, pFrom.Y, pTo.X, pTo.Y), 255);
    end;
    EndScene;
  end;
  Self.Caption := Format('(%0.0f;%0.0f)', [X, Y]);
end;

procedure TfrmMain.recBoardMouseUp(Sender: TObject; Button: TMouseButton; Shift: TShiftState; X, Y: Single);
begin
  with bmp.Canvas do
  begin
    BeginScene;
    DrawEllipse(RectF(pFrom.X, pFrom.Y, pTo.X, pTo.Y), 255);
    EndScene;
  end;
  pFrom := PointF(-1, -1);
end;


















end.
票数 4
EN

Stack Overflow用户

发布于 2012-04-26 07:55:28

我最终做的是-基于上面Whiler的洞察,是在“绘制例程”(即按下鼠标)开始时存储位图的状态,然后在MouseMove上,在我渲染新的线条之前(在这个例子中),我恢复状态,然后绘制新的线条……

代码语言:javascript
复制
procedure TFMXDrawSurface.DrawSurfaceMouseDown(Sender: TObject; Button: TMouseButton; Shift: TShiftState; X, Y: Single);
begin
  FOrigin := PointF(X, Y);
  FMovePt := PointF(X, Y);
  FPrevPt := PointF(X, Y);
  FDrawing := True;
  FTempDrawbitmap.Assign(FDrawSurface.Bitmap);
end;

procedure TFMXDrawSurface.DrawSurfaceMouseMove(Sender: TObject; Shift: TShiftState; X, Y: Single);
begin
  if FDrawing then
  begin
    DrawShape(FOrigin, FMovePt);
    FMovePt := PointF(X, Y);
    DrawShape(FOrigin, FMovePt);
    FPrevPt := PointF(X, Y);
  end;
end;

procedure TFMXDrawSurface.DrawShape(TopLeft, BottomRight: TPointF);
var
  R: TRectF;
begin
  FDrawSurface.Bitmap.Canvas.BeginScene;
  try

    case FShapeToDraw of
      doLine:
      begin
        // restore canvas to initial state so we don't keep old movement data around
        R.TopLeft := PointF(0.0, 0.0);
        R.BottomRight := PointF(FDrawSurface.Width, FDrawSurface.Height);
        FDrawSurface.Bitmap.Canvas.DrawBitmap(FTempDrawBitmap, R, R, 100);
        FDrawSurface.Bitmap.Canvas.RestoreState(FDrawState);
        FDrawSurface.Bitmap.Canvas.DrawLine(PointF(TopLeft.X, TopLeft.Y), PointF(BottomRight.X, BottomRight.Y), 100);
      end;
    end;
  finally
    FDrawSurface.Bitmap.Canvas.EndScene;
    FDrawSurface.Bitmap.BitmapChanged;
  end;

end;

它是有效的,但我不知道这是不是“正确”的方式...

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/10291330

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档