C#透明面板刷新问题
我目前正在开发一个需要在透明面板上显示动画的项目。我已经能够创建一个透明面板并在其上绘图,但是当我刷新面板时,我用钢笔工具绘制的位置不会被重新绘制为透明。这是我之前在面板上绘制的内容的最后一个位置。
我认为有一种简单的方法可以覆盖 OnPaint 或 Refresh 以将面板上的所有像素重新绘制为透明,但我无法在网上找到解决方案或自己找出解决方案。
这是我用来使背景透明的代码:
public class TransparentPanel : Panel
{
protected override CreateParams CreateParams
{
get
{
CreateParams cp = base.CreateParams;
cp.ExStyle |= 0x20;
return cp;
}
}
protected override void OnPaintBackground(PaintEventArgs e)
{
}
}
这是我将背景重新绘制为透明的最佳失败尝试:
protected override void OnPaint(PaintEventArgs pe)
{
pe.Graphics.FillRectangle(new SolidBrush(Color.FromArgb(100,255,255,255)), this.ClientRectangle);
}
此解决方案的问题是,几次刷新后背景会变成不透明的白色。
谁能帮我弄清楚如何做到这一点?我对图形和动画非常陌生,我认为这有一个相当简单的答案。提前致谢。
***编辑*** 根据 Dyppl 的回复,我改变了在面板上绘制图形的方式。这是我当前的代码:
public TransparentPanel fighterPanel;
...
fighterPanel.Paint +=new PaintEventHandler(fighterPanel_Paint);
...
fighterPanel = new TransparentPanel();
fighterPanel.Location = new System.Drawing.Point(600, 300);
fighterPanel.Size = new System.Drawing.Size(400, 400);
gameArenaForm.Controls.Add(fighterPanel);
fighterPanel.BringToFront();
...
private void fighterPanel_Paint(object sender, PaintEventArgs e)
{
using (Pen blackPen = new Pen(Color.Black, 3), redPen = new Pen(Color.Red, 3), bluePen = new Pen(Color.Blue, 3))
{
//head
e.Graphics.DrawEllipse
(blackPen,
head.DrawPoint(torso.GetTorsoAngle(), torso.neck.getLocationX(), torso.neck.getLocationY()).X,
head.DrawPoint(torso.GetTorsoAngle(), torso.neck.getLocationX(), torso.neck.getLocationY()).Y,
head.radius * 2,
head.radius * 2
);
//torso
e.Graphics.DrawLine(blackPen, torso.neck.getLocationX(), torso.neck.getLocationY(), torso.shoulders.getLocationX(), torso.shoulders.getLocationY());
e.Graphics.DrawLine(blackPen, torso.shoulders.getLocationX(), torso.shoulders.getLocationY(), torso.hips.getLocationX(), torso.hips.getLocationY());
//right arm
e.Graphics.DrawLine(blackPen, torso.shoulders.getLocationX(), torso.shoulders.getLocationY(), rightArm.elbow.getLocationX(), rightArm.elbow.getLocationY());
e.Graphics.DrawLine(redPen, rightArm.elbow.getLocationX(), rightArm.elbow.getLocationY(), rightArm.attachHand.getLocationX(), rightArm.attachHand.getLocationY());
//left arm
e.Graphics.DrawLine(blackPen, torso.shoulders.getLocationX(), torso.shoulders.getLocationY(), leftArm.elbow.getLocationX(), leftArm.elbow.getLocationY());
e.Graphics.DrawLine(bluePen, leftArm.elbow.getLocationX(), leftArm.elbow.getLocationY(), leftArm.attachHand.getLocationX(), leftArm.attachHand.getLocationY());
//right leg
e.Graphics.DrawLine(blackPen, torso.hips.getLocationX(), torso.hips.getLocationY(), rightLeg.knee.getLocationX(), rightLeg.knee.getLocationY());
e.Graphics.DrawLine(redPen, rightLeg.knee.getLocationX(), rightLeg.knee.getLocationY(), rightLeg.attachFoot.getLocationX(), rightLeg.attachFoot.getLocationY());
//left leg
e.Graphics.DrawLine(blackPen, torso.hips.getLocationX(), torso.hips.getLocationY(), leftLeg.knee.getLocationX(), leftLeg.knee.getLocationY());
e.Graphics.DrawLine(bluePen, leftLeg.knee.getLocationX(), leftLeg.knee.getLocationY(), leftLeg.attachFoot.getLocationX(), leftLeg.attachFoot.getLocationY());
}
}
以下是对象移动和刷新几次之前和之后的一些图片:
对不起,它除非我有 10 个代表,否则不会让我嵌入图像。
I'm currently working on a project that requires animation on a transparent panel. I have been able to create a transparent panel and draw on it, but when I refresh the panel, where I have drawn with the pen tool is not being redrawn as transparent. This is leaves the last position of what I drew previously stained on the panel.
I assume there is a simple way to override OnPaint or Refresh to redraw all of the pixels on the panel as transparent, but I can't find a solution online or figure it out myself.
Here is the code I used to make the background transparent:
public class TransparentPanel : Panel
{
protected override CreateParams CreateParams
{
get
{
CreateParams cp = base.CreateParams;
cp.ExStyle |= 0x20;
return cp;
}
}
protected override void OnPaintBackground(PaintEventArgs e)
{
}
}
This was my best failed attempt to redraw the background as transparent:
protected override void OnPaint(PaintEventArgs pe)
{
pe.Graphics.FillRectangle(new SolidBrush(Color.FromArgb(100,255,255,255)), this.ClientRectangle);
}
The problem with this solution is that the background becomes opaque white after a couple refreshes.
Can anyone help me figure out how to do this? I'm super new to graphics and animation, and I assume this has a fairly simple answer. Thanks in advance.
***EDIT***
As per Dyppl's response I have changed the way I draw the graphics to the panel. Here is my current code:
public TransparentPanel fighterPanel;
...
fighterPanel.Paint +=new PaintEventHandler(fighterPanel_Paint);
...
fighterPanel = new TransparentPanel();
fighterPanel.Location = new System.Drawing.Point(600, 300);
fighterPanel.Size = new System.Drawing.Size(400, 400);
gameArenaForm.Controls.Add(fighterPanel);
fighterPanel.BringToFront();
...
private void fighterPanel_Paint(object sender, PaintEventArgs e)
{
using (Pen blackPen = new Pen(Color.Black, 3), redPen = new Pen(Color.Red, 3), bluePen = new Pen(Color.Blue, 3))
{
//head
e.Graphics.DrawEllipse
(blackPen,
head.DrawPoint(torso.GetTorsoAngle(), torso.neck.getLocationX(), torso.neck.getLocationY()).X,
head.DrawPoint(torso.GetTorsoAngle(), torso.neck.getLocationX(), torso.neck.getLocationY()).Y,
head.radius * 2,
head.radius * 2
);
//torso
e.Graphics.DrawLine(blackPen, torso.neck.getLocationX(), torso.neck.getLocationY(), torso.shoulders.getLocationX(), torso.shoulders.getLocationY());
e.Graphics.DrawLine(blackPen, torso.shoulders.getLocationX(), torso.shoulders.getLocationY(), torso.hips.getLocationX(), torso.hips.getLocationY());
//right arm
e.Graphics.DrawLine(blackPen, torso.shoulders.getLocationX(), torso.shoulders.getLocationY(), rightArm.elbow.getLocationX(), rightArm.elbow.getLocationY());
e.Graphics.DrawLine(redPen, rightArm.elbow.getLocationX(), rightArm.elbow.getLocationY(), rightArm.attachHand.getLocationX(), rightArm.attachHand.getLocationY());
//left arm
e.Graphics.DrawLine(blackPen, torso.shoulders.getLocationX(), torso.shoulders.getLocationY(), leftArm.elbow.getLocationX(), leftArm.elbow.getLocationY());
e.Graphics.DrawLine(bluePen, leftArm.elbow.getLocationX(), leftArm.elbow.getLocationY(), leftArm.attachHand.getLocationX(), leftArm.attachHand.getLocationY());
//right leg
e.Graphics.DrawLine(blackPen, torso.hips.getLocationX(), torso.hips.getLocationY(), rightLeg.knee.getLocationX(), rightLeg.knee.getLocationY());
e.Graphics.DrawLine(redPen, rightLeg.knee.getLocationX(), rightLeg.knee.getLocationY(), rightLeg.attachFoot.getLocationX(), rightLeg.attachFoot.getLocationY());
//left leg
e.Graphics.DrawLine(blackPen, torso.hips.getLocationX(), torso.hips.getLocationY(), leftLeg.knee.getLocationX(), leftLeg.knee.getLocationY());
e.Graphics.DrawLine(bluePen, leftLeg.knee.getLocationX(), leftLeg.knee.getLocationY(), leftLeg.attachFoot.getLocationX(), leftLeg.attachFoot.getLocationY());
}
}
Here are some pictures of before and after the object moves and refreshes a few times:
Sorry, it won't let me embed the images unless I have 10 Rep.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
您不应该使用
CreateGraphics
来完成您的任务。订阅面板的Paint
事件,并使用PaintEventArgs.Graphics
作为Graphics
对象在事件处理程序中完成所有绘图。以下是我使用您的
TransparentPanel
和我的事件处理程序得到的结果:更新:问题是您必须在每个绘制周期开始时调用 Graphics.Clear 方法才能删除所有先前的绘图。它会弄乱你的透明背景。 此链接为您提供一些建议关于这个问题。关键点是您还应该使面板的父控件无效以获得“透明”背景。
因此,我保持
TransparentPanel
的代码不变,但更改了主窗体的代码:现在,每当我单击窗体上的按钮时,面板都会重新绘制并在随机位置显示一个矩形。如果您使 transparantPanel1 本身无效,它将不会被清除,您会看到一堆红色矩形。
更新(亚历克斯):
这是 Dyppl 链接中提供的解决问题的代码。它只需要放置在透明面板类中:
我在面板上的每次刷新时调用此代码,它使背景保持透明。
You shouldn't use
CreateGraphics
for your task. Subscribe to thePaint
event of your panel and do all your drawing in the event handler usingPaintEventArgs.Graphics
as aGraphics
object instead.Here's what I got using your
TransparentPanel
and my event handler:UPDATE: The problem is that you have to call
Graphics.Clear
method in the beginning of every draw cycle in order to get rid of all previous drawings. It will mess up your transparent background. This link gives you some advices regarding the problem. The Key point is that you should invalidate the parent control of your panel as well to get your "transparent" background.So, I left the code of
TransparentPanel
untouched but changed the code of main form:Now, whenever I click the button on my form the panel gets redrawn and shows one rectangle in random location. If you invalidate the transparantPanel1 itself, it won't clear and you'll see a mess of red rectangles.
UPDATED (By Alex):
This is the code provided in the link from Dyppl that solved the problem. It just needs to be placed in the transparent panel class:
I call this code at every refresh on the panel and it keeps the background transparent.