Delphi 如何从TCanvas中删除单个图片?
在我的表单中,有一个包含画布的透明面板(我认为它的实现在这里并不重要;有人告诉我不是这样)。我正在这个画布上绘制许多位图,使用:Delphi 如何从TCanvas中删除单个图片?,delphi,canvas,bitmap,delphi-xe3,Delphi,Canvas,Bitmap,Delphi Xe3,在我的表单中,有一个包含画布的透明面板(我认为它的实现在这里并不重要;有人告诉我不是这样)。我正在这个画布上绘制许多位图,使用: Panel.Canvas.Draw(Image.Left, Image.Top, Image.Picture.Bitmap, Opacity); //Image is a TImage instance //Opacity is an integer 0..255 但是,当我在图片中做一些改变时,比如重新确定尺寸或在表格周围移动,我会在面板中重新绘制它的图片。这里的
Panel.Canvas.Draw(Image.Left, Image.Top, Image.Picture.Bitmap, Opacity);
//Image is a TImage instance
//Opacity is an integer 0..255
但是,当我在图片中做一些改变时,比如重新确定尺寸或在表格周围移动,我会在面板中重新绘制它的图片。这里的问题是旧的定位图像仍保留在画布上。
现在我的问题是:有一种方法可以擦除画布上的单个位图吗?如果是,会是什么?如果没有,有没有办法擦除画布上的所有内容?这样我就可以重新绘制剩余的图片
编辑:
最后,我的问题出现在我使用的透明面板上。它的
Paint
方法是伪造的,并没有使画布失效以擦除其上的控件。无论如何,问题解决了。我该怎么处理这个问题呢?不太可能,因为画布没有记录不同的图像
但是,只需在画布上画图,就可以轻松地“清除”画布的任何部分。这将允许您重新绘制所有剩余的图片 但是,如果有许多图片,并且用户正忙于拖动单个图片,那么这可能会非常耗时;因为这将导致对运动图像的每个微小位置改变进行大量重绘 一个选项是在调整“活动”图像时使用XOR掩码绘制该图像。然后,只需再次使用异或掩码在同一位置重新绘制即可擦除。这样做的缺点是颜色会失真,但效率很高 另一个选项是在绘制活动图片之前,复制画布的一部分。然后,您有一个简单的机制,通过在正确的位置重新绘制副本来擦除新图片
编辑:回应Guill评论的最后一个选项的详细说明: 既然我没有背景,我怎么能画出来呢?有透明的刷子吗 假设要绘制和移动图片(可能是一个蓝色矩形20x60):
- 假设您从一块空白画布开始,
backgroundclWhite
- 初始位置为(25,75),因此:
- (A)首先在画布上复制(25,75)处的20x60矩形
- 副本当然是完全白色的,但那正是你的背景
- 现在在该位置绘制矩形
- 在(25,75)处绘制复制的图像NB完全没有透明度!在绘制蓝色矩形之前,您希望将画布恢复到(A)的状态
- 在(40,90)处复制20x60矩形。(同样,它将是完全白色的)
- 在(40,90)处绘制蓝色矩形
- 我们将放弃当前副本,因为我们不再希望移动蓝色矩形
- 我们希望将红色矩形放置在(45,95)处,使其与蓝色重叠
- (B)在(45,95)处复制80x10矩形
- 注意,这一次副本的一部分是蓝色的,其余部分是白色的
- 现在在(45,95)处绘制红色矩形
- 绘制复制的图像(45,95)NB同样重要的是,我们不要使用透明度,因为我们试图将绘制红色矩形的图像部分恢复到(B)中的样子
- 在(45,95)处复制5x5矩形
- 绘制较小的红色矩形
旁注:如果您正在绘制的图像是不规则形状,则无所谓。如果你的备份矩形完全覆盖了你正在绘制的图像,这项技术是有效的。你的整个绘制方法是不正确的。绘制表面的窗口不记得其内容。在窗口中绘制的设计要求每个窗口在被请求时能够重新绘制自身,即当发送
WM_paint
消息时。您必须通过绘制要求您绘制的内容来响应WM_PAINT
。您当前正在违反该规则。你需要重新设计你的程序以适应这个系统
请执行以下操作:
t输入框
添加到面板中OnPaint
事件处理程序添加到执行所有绘制的绘制框中Invalidate
WM_PAINT
。这是因为VCL为您包装了所有内容,并以更易于消化的形式呈现
关于这个主题(以及其他许多主题)的必读读物是Petzold的经典著作《编程窗口》。没有办法从画布上“清除”一些东西。您只能要求面板重新绘制,例如通过调用
panel.Invalidate
,下一步您将不会绘制隐藏图像。或者你可以在那个区域画些东西。你到底要做什么?我将把我的问题更新为更具体的示例。简而言之,它要求系统通过发送WM_PAINT
消息重新绘制系统响应的控件,该消息通常由控件作为OnPaint
事件发布。在这种情况下,你应该把所有的东西都画出来。但这不适用于面板。面板主要不用于自定义绘图。我明白了。但是在一个大循环中使用它会导致很多“闪烁”。并没有解决我的问题,因为它确实重新绘制了旧的定位图像