Delphi &引用;“对象锁未拥有”;使用OnPaint方法时出错
我试图用OnPaint方法绘制一个简单的图像。代码编译得很好,但当应用程序启动时,会显示“Object lock not owned”错误,而不会发生其他任何事情。你能告诉我我犯了什么错误吗?代码显示了我正在使用的OnPaint事件。谢谢大家的帮助Delphi &引用;“对象锁未拥有”;使用OnPaint方法时出错,delphi,firemonkey,Delphi,Firemonkey,我试图用OnPaint方法绘制一个简单的图像。代码编译得很好,但当应用程序启动时,会显示“Object lock not owned”错误,而不会发生其他任何事情。你能告诉我我犯了什么错误吗?代码显示了我正在使用的OnPaint事件。谢谢大家的帮助 procedure TTabbedForm.Image1Paint(Sender: TObject; Canvas: TCanvas; const ARect: TRectF); var p1, p2, p3, p4, p5, p6: T
procedure TTabbedForm.Image1Paint(Sender: TObject; Canvas: TCanvas;
const ARect: TRectF);
var
p1, p2, p3, p4, p5, p6: TPointF;
prst1: TRectF;
i :Integer;
begin
Image1.Bitmap.Canvas.Stroke.Color := TAlphaColors.Black;
Image1.Bitmap.Canvas.Stroke.Thickness := 3;
p1 := TPointF.Create(PX, PY);
Image1.Bitmap.Canvas.BeginScene;
with TabbedForm do begin
for i := 0 to 360 do
if (i mod 15)=0 then
begin
p2 := TPointF.Create(Round(PX+PP*sin(i*pi/180)), Round(PY+PP*cos(i*pi/180)));
Image1.Bitmap.Canvas.DrawLine(p1, p2, 100);
end;
for i := 0 to PP do
if (i mod 20)=0 then
begin
prst1 := TRectF.Create(PX+i,PY+i,PX-i,PY-i);
Image1.Bitmap.Canvas.DrawEllipse(prst1, 100);
end;
for i := 0 to 400 do
if (i mod 20)=0 then
begin
p3 := TPointF.Create(i,2*PP);
p4 := TPointF.Create(i,2*PP+2*PP);
Image1.Bitmap.Canvas.DrawLine(p3, p4, 100);
end;
for i := 0 to 400 do
if (i mod 20)=0 then
begin
p5 := TPointF.Create(0,2*PP+i);
p6 := TPointF.Create(2*PP+2*PP,2*PP+i);
Image1.Bitmap.Canvas.DrawLine(p5, p6, 100);
end;
Image1.Bitmap.Canvas.EndScene;
end;
end;
我想你会收到这个错误信息,因为你在画布上画画的时候你是不被允许的。造成这种情况的潜在原因是:
- 您正在图像的绘制事件中绘制图像的位图。图像用于显示预生成或加载的位图,由于修改位图会触发OnPaint事件,我认为从同一事件中进行这些更改是一个坏主意。它要求一个无休止的循环,或其他不必要的副作用
- 您使用的BeginScene/EndScene不正确。只有当BeginScene返回true时,才应继续绘制。实际上,在给定的画布上绘制绘制事件时,根本不需要调用它们
- 您(部分)使用表单的全局实例而不是当前实例(Self),这可能(取决于您的应用程序)导致在错误的实例上绘制
- 使用TPaintbox(您必须添加名为“Paintbox1”的TPaintbox,并将此方法添加到其OnPaint处理程序)。油漆盒用于直接绘图。如果您能够在特定事件上预渲染图像的位图,例如启动应用程序、单击按钮、定时器等,则还可以保留图像
- 正确使用BeginScene和EndScene,使用
和if
块。BeginScene是否会给您一个锁,并根据成功与否返回一个布尔值。只有在实际获得锁的情况下才能继续,在这种情况下也只能调用EndScene,因为它们是ref计数的,如果这样做错误,可能会破坏ref计数,从而导致应用程序中的所有后续绘制try..finally
- 场景中的笔划设置也是如此。不是100%确定是否需要,但我想这也是绘制场景的一部分,对吗
- 完全忽略
。Paintbox或Image控件应该已经调用了它自己。看BeginScene..EndScene
- 只需使用
。它作为参数传递给事件处理程序,因此最好使用它,然后自己尝试找到合适的画布Canvas
- 用删除了
。这有点遥不可及,但看起来您引用的是一个全局
变量,而且由于您在TTabbedForm方法中,因此应该能够按原样使用当前实例的属性和方法,或者在遇到命名冲突时使用TTabbedForm
。表单和数据模块最好不要依赖于这些全局变量,如果希望表单有多个实例,那么实际上会遇到问题,在这种情况下,您的原始代码会部分地在错误的实例上运行Self.
程序TTabbedForm.Paintbox1Paint(
发送方:TObject;Canvas:TCanvas;const-ARect:TRectF);
变量
p1,p2,p3,p4,p5,p6:TPointF;
prst1:TRectF;
i:整数;
开始
p1:=TPointF.Create(PX,PY);
Canvas.Stroke.Color:=TAlphaColors.Black;
Canvas.Stroke.Thickness:=3;
对于i:=0到360 do
如果(i mod 15)=0,则
开始
p2:=TPointF.Create(圆形(PX+PP*sin(i*pi/180)),圆形(PY+PP*cos(i*pi/180));
帆布拉丝(p1、p2、100);
结束;
对于i:=0到PP do
如果(i mod 20)=0,则
开始
prst1:=TRectF.Create(PX+i,PY+i,PX-i,PY-i);
帆布抽屉(prst1,100);
结束;
对于i:=0到400 do
如果(i mod 20)=0,则
开始
p3:=TPointF.Create(i,2*PP);
p4:=TPointF.Create(i,2*PP+2*PP);
帆布拉丝(p3、p4、100);
结束;
对于i:=0到400 do
如果(i mod 20)=0,则
开始
p5:=TPointF.Create(0,2*PP+i);
p6:=TPointF.Create(2*PP+2*PP,2*PP+i);
帆布拉丝(p5、p6、100);
结束;
结束;
我想您会收到此错误消息,因为您在画布上绘图时,不允许这样做。造成这种情况的潜在原因是:
- 您正在图像的绘制事件中绘制图像的位图。图像用于显示预生成或加载的位图,由于修改位图会触发OnPaint事件,我认为从同一事件中进行这些更改是一个坏主意。它要求一个无休止的循环,或其他不必要的副作用
- 您使用的BeginScene/EndScene不正确。只有当BeginScene返回true时,才应继续绘制。实际上,在给定的画布上绘制绘制事件时,根本不需要调用它们
- 您(部分)使用表单的全局实例而不是当前实例(Self),这可能(取决于您的应用程序)导致在错误的实例上绘制
- 使用TPaintbox(您必须添加名为“Paintbox1”的TPaintbox,并将此方法添加到其OnPaint处理程序)。油漆盒用于直接绘图。如果能够预渲染,也可以保留图像
procedure TTabbedForm.Button1Click(Sender: TObject); var p1, p2, p3, p4, p5, p6: TPointF; prst1: TRectF; i: integer; begin Image1.Bitmap.SetSize(300, 300); // must be set before call to BeginScene if Image1.Bitmap.Canvas.BeginScene then try Image1.Bitmap.Canvas.Stroke.Color := TAlphaColors.Black; Image1.Bitmap.Canvas.Stroke.Thickness := 1; p1 := TPointF.Create(px, py); for i := 0 to 360 do if (i mod 15) = 0 then begin pp := i; p2 := TPointF.Create(Round(px + pp * sin(i * pi / 180)), Round(py + pp * cos(i * pi / 180))); Image1.Bitmap.Canvas.DrawLine(p1, p2, 100); end; for i := 0 to pp do ... for i := 0 to 400 do ... for i := 0 to 400 do .... finally Image1.Bitmap.Canvas.EndScene; end; end;