为什么我不能使用onClick事件处理程序在lazarus中的表单上绘制形状?

时间:2016-04-07 11:24:59

标签: delphi lazarus

我的事件处理程序如下:

procedure TfrmCanvasMethods.btnShapesClick(Sender: TObject);
begin
    Canvas.Rectangle(40, 40, 400, 200);
    Canvas.Rectangle(80, 80, 360, 160);
    Canvas.Ellipse(150, 50, 290, 190);
    Canvas.Ellipse(100, 100, 340, 140);
end;                      

我正在使用Mac OS X

1 个答案:

答案 0 :(得分:4)

您必须阅读有关图形窗口系统的基础知识。无论是Windows,MacOS还是UNIX X Window。

几乎普遍认为不是决定何时,何地以及在何处绘制的应用程序。操作系统决定这样做并询问应用程序何时执行此操作。所有应用程序都可以做 - 是使窗口的某些部分无效 - 即通知操作系统窗口的某些部分不再有效,然后等到操作系统希望重新绘制该部分(如果无效的窗口被最小化或被另一个窗口覆盖,则可能永远不会),然后 - 只有这样 - 进行绘制。

那你怎么能这样做?

方法1 :精通资源并接近真实的操作系统工作流程。

您将TPaintbox放在整个form上。

您将矩形和圆圈保留为表单变量中的不可见记录或类。当这些数字被更改时(例如:您添加了另一个矩形,或者增加了一些圆直径),您调用MyForm.MyPaintBox.Invalidate以通知操作系统该painboxt的图像不再有效。当操作系统认为刷新图像时是及时的,它会调用MyForm.MyPaintBox.OnPaint事件,在这种情况下,您可以调用MyPaintBox.Canvas.Rectangle(40, 40, 400, 200);这样的调用。注意 - 您将重新绘制paintbox的画布,而不是表单的画布!

procedure TfrmCanvasMethods.btnShapesClick(Sender: TObject);
begin
  MyPaintBox.Invalidate();  
end;

procedure TfrmCanvasMethods.MyPaintBoxPaint(Sender: TObject);
var Canvas: TCanvas;
begin
  Canvas := MyPaintbox.Canvas;

    Canvas.Rectangle(40, 40, 400, 200);
    Canvas.Rectangle(80, 80, 360, 160);
    Canvas.Ellipse(150, 50, 290, 190);
    Canvas.Ellipse(100, 100, 340, 140);
end;

方法2 :懒惰和资源膨胀

您将TImage放在整个form上。

该图像将具有您想要的任何图片的隐式位图。更重要的是,它会跟踪您对该图片的绘制,并自动调用Invalidate并自动处理操作系统的重绘请求。

procedure TfrmCanvasMethods.btnShapesClick(Sender: TObject);
var Canvas: TCanvas;
begin
  MyImage.Picture.Bitmap.SetSize( MyImage.ClientWidth, MyImage.ClientHeight );

  Canvas := MyImage.Picture.Bitmap.Canvas;

    Canvas.Rectangle(40, 40, 400, 200);
    Canvas.Rectangle(80, 80, 360, 160);
    Canvas.Ellipse(150, 50, 290, 190);
    Canvas.Ellipse(100, 100, 340, 140);
end;

然而,价格可能会分配可能多达几兆字节的内存,而不仅仅是在操作系统需要刷新表单图片时为那些相对罕见的情况保留图片。