【愚公系列】2023年11月 GDI+绘图专题(裁剪、变换、重绘)
🏆 作者简介,愚公搬代码
🏆《头衔》:华为云特约编辑,华为云云享专家,华为开发者专家,华为产品云测专家,CSDN博客专家,阿里云专家博主,腾讯云优秀博主,掘金优秀博主,51CTO博客专家等。
🏆《近期荣誉》:2022年CSDN博客之星TOP2,2022年华为云十佳博主等。
🏆《博客内容》:.NET、Java、Python、Go、Node、前端、IOS、Android、鸿蒙、Linux、物联网、网络安全、大数据、人工智能、U3D游戏、小程序等相关领域知识。
🏆🎉欢迎 👍点赞✍评论⭐收藏
🚀前言
裁剪(Clipping)指的是将图像或元素的一部分进行裁剪,只显示所需区域,而隐藏不需要的部分。
变换(Transforming)指的是将图像或元素进行缩放、旋转、平移等操作,以改变其大小、方向或位置。
重绘(Repainting)指的是根据新的布局或者样式信息,重新绘制图像或元素的外观。当元素的位置、大小、样式发生变化时,需要重新绘制来更新外观。
这些操作常常在图形处理、界面设计、游戏开发等领域中使用。
🚀一、裁剪
🔎1.SetClip
Graphics.SetClip 方法是 GDI+ 绘图中的一个方法,它可以设置裁剪区域,以便在绘制图形时只绘制指定区域内的部分。该方法可以接受多种类型的参数来指定裁剪区域,例如一个矩形、一个多边形、一个路径和一个区域等。
下面是一个使用 Graphics.SetClip 方法设置裁剪区域的示例:
private void Form1_Paint(object sender, PaintEventArgs e)
{
Graphics graphics = e.Graphics;
// 绘制矩形
Rectangle rect = new Rectangle(10, 10, 100, 100);
graphics.DrawRectangle(Pens.Black, rect);
// 设置裁剪区域为矩形的一半
Rectangle clipRect = new Rectangle(10, 10, 50, 100);
Region region = new Region(clipRect);
graphics.SetClip(region, CombineMode.Replace);
// 绘制椭圆
Rectangle ellipseRect = new Rectangle(50, 50, 100, 50);
graphics.FillEllipse(Brushes.Red, ellipseRect);
}
private void button1_Click(object sender, EventArgs e)
{
// 重绘图形
Invalidate();
}
在上述代码中,首先绘制了一个矩形,然后使用 Region
对象指定了一个裁剪区域。接着使用 Graphics.SetClip
方法将该区域设置为裁剪区域,只有该区域内的图形才会被绘制。在此之后绘制了一个椭圆,它只被绘制在了矩形的左半部分区域内。
需要注意的是,裁剪区域可以通过多次调用 Graphics.SetClip
方法来叠加,也可以通过 Graphics.ResetClip
方法清除。而裁剪模式则可以用 CombineMode
枚举类型来指定,例如 CombineMode.Replace
、CombineMode.Intersect
、CombineMode.Union
和 CombineMode.Exclude
等等。
🚀二、重绘
🔎1.Invalidate
Invalidate是在Graphics中使用的方法之一,它用于指示Graphics对象无效并需要重新绘制。当调用该方法时,Graphics对象将被标记为需要重新绘制,在屏幕更新之前将使用新的绘图数据更新。使用Invalidate方法是在屏幕上显示动态图形的一种常见方法。调用Invalidate方法后,必须等待下一次屏幕更新才能看到更新后的图形。
与之相对应的方法是Refresh方法。Refresh方法会立即重绘Graphics对象,而不是等待下一次屏幕更新。因此,如果您需要立即更新图形,可以使用Refresh方法。
如果您正在处理与用户交互的图形,例如响应鼠标单击事件,则可能需要使用Invalidate方法来更新屏幕上的图形,而不是使用Refresh。如果使用Refresh,则可能会在用户交互时引起闪烁或不必要的图形更新。
以下是一个简单的案例,演示如何在WinForm中使用Invalidate方法进行GDI+绘图的重绘:
//在窗体中定义一个标志位,用于指示是否需要重新绘制图形
private bool isNeedToRedraw = false;
//在窗体中定义一个方法,用于绘制图形
private void DrawGraphics(Graphics g)
{
//绘制代码
}
//在窗体的Paint事件中调用DrawGraphics方法进行绘制
private void Form1_Paint(object sender, PaintEventArgs e)
{
if (isNeedToRedraw)
{
DrawGraphics(e.Graphics);
}
}
//在窗体的其他事件中调用Invalidate方法进行图形更新
private void button1_Click(object sender, EventArgs e)
{
isNeedToRedraw = true;
this.Invalidate();
}
//在窗体的Load事件中设置双缓冲
private void Form1_Load(object sender, EventArgs e)
{
this.SetStyle(ControlStyles.AllPaintingInWmPaint | ControlStyles.DoubleBuffer | ControlStyles.UserPaint, true);
this.UpdateStyles();
}
在上述代码中,我们定义了一个标志位isNeedToRedraw
,用于指示是否需要重新绘制图形。在窗体的Paint事件中,如果标志位为True,则调用DrawGraphics方法进行绘制。
在窗体的其他事件中,例如按钮单击事件,我们将标志位设置为True,并调用Invalidate方法来更新图形。通过这种方式,我们可以确保只有在需要更新图形时才执行绘图操作,从而提高了程序的效率。
为了避免出现图形闪烁的情况,我们在窗体的Load事件中设置了双缓冲。这样可以在绘制时使用一个缓存图像,等绘制完成后再将整个图像一次性绘制到屏幕上,从而消除了图形闪烁的问题。
🚀三、变换
🔎1.缩放
GDI+通过ScaleTransform方法实现图形缩放,该方法可以在水平方向和垂直方向上分别缩放图形。具体使用方法如下:
//在Graphics对象上调用ScaleTransform方法
graphics.ScaleTransform(float scaleX, float scaleY);
其中,scaleX和scaleY分别表示水平方向和垂直方向上的缩放比例,它们的取值范围是0到正无穷大的浮点数。
下面是一个简单的案例,演示如何使用ScaleTransform方法实现图形的缩放:
//创建一个Graphics对象
Graphics g = e.Graphics;
//设置缩放比例
float scaleX = 2.0f;
float scaleY = 1.5f;
g.DrawRectangle(Pens.Red, 10, 10, 50, 50);
//调用ScaleTransform方法进行缩放
g.ScaleTransform(scaleX, scaleY);
//绘制图形
g.DrawLine(Pens.Black, 0, 0, 100, 100);
g.DrawRectangle(Pens.Red, 10, 10, 50, 50);
在上述代码中,我们在窗体的Paint事件中创建了一个Graphics对象,然后设置了水平方向上的缩放比例为2,垂直方向上的缩放比例为1.5。
接着,我们调用Graphics对象的ScaleTransform方法进行缩放,并使用DrawLine和DrawRectangle方法绘制了一条直线和一个矩形。在绘制时,由于已经对图形进行了缩放,因此绘制出的直线和矩形大小与原来的大小不同。
需要注意的是,ScaleTransform方法是矩阵变换的一种,因此会对Graphics对象上所有的绘制操作产生影响,包括线条粗细、字体大小等。如果需要还原Graphics对象的状态,可以使用ResetTransform方法,该方法会将Graphics对象的矩阵变换重置为默认状态。
🔎2.平移
在Graphics中,可以使用TranslateTransform方法来实现平移。该方法可将平移量添加到当前的坐标系中,从而实现平移效果。
下面是一个简单的示例代码:
//创建一个Graphics对象
Graphics g = e.Graphics;
g.DrawRectangle(Pens.Red, 10, 10, 50, 50);
//调用ScaleTransform方法进行缩放
g.TranslateTransform(100, 50);
//绘制图形
g.DrawLine(Pens.Black, 0, 0, 100, 100);
g.DrawRectangle(Pens.Red, 10, 10, 50, 50);
使用TranslateTransform方法将坐标系平移100个单位的水平方向和50个单位的垂直方向。最后,在平移后的位置绘制一个矩形。注:实际上这里的矩形的左上角坐标为原点坐标(0,0),但是因为平移了 (100,50) 的距离,所以它在屏幕上显示的位置应该是 (100,50)。最后,释放Graphics对象的资源。
通过修改TranslateTransform方法中的参数,可以实现不同的平移效果。例如,如果将平移量改为(-50, 100),则坐标系将向上平移50个单位,向左平移100个单位。
g.TranslateTransform(-50, 100);
需要注意的是,TranslateTransform方法不会改变绘图对象的位置,而是会改变坐标系的位置。如果要将绘图对象移动到新的位置,应该使用其他的绘图方法或属性,例如DrawRectangle方法中的x和y参数。
🔎3.旋转
在使用Graphics进行绘图时,可以使用RotateTransform方法实现旋转操作。该方法可以应用一个旋转变换到当前的Graphics对象上,从而改变绘制的方向。
具体操作步骤如下:
-
创建一个Graphics对象,例如:
Graphics g = this.CreateGraphics();
-
调用RotateTransform方法实现旋转操作,例如:
g.RotateTransform(45);
该方法需要一个参数,表示旋转的角度。这里的参数为45度,表示将当前的Graphics对象旋转45度。
-
在旋转后的Graphics对象上进行绘制操作,例如:
g.DrawLine(pen, 0, 0, 100, 0);
这里使用DrawLine方法在旋转后的Graphics对象上绘制一条线段,起点坐标为(0,0),终点坐标为(100,0)。
-
重置Graphics对象的变换,以便后续的绘制操作不受影响,例如:
g.ResetTransform();
这里使用ResetTransform方法重置Graphics对象的变换,以便后续的绘制操作不受影响。
完整的代码示例如下:
//创建一个Graphics对象
Graphics g = e.Graphics;
g.DrawRectangle(Pens.Red, 10, 10, 50, 50);
g.TranslateTransform(100, 50);
//调用ScaleTransform方法进行缩放
g.RotateTransform(45);
//绘制图形
g.DrawLine(Pens.Black, 0, 0, 100, 100);
g.DrawRectangle(Pens.Red, 10, 10, 50, 50);
🚀感谢:给读者的一封信
亲爱的读者,
我在这篇文章中投入了大量的心血和时间,希望为您提供有价值的内容。这篇文章包含了深入的研究和个人经验,我相信这些信息对您非常有帮助。
如果您觉得这篇文章对您有所帮助,我诚恳地请求您考虑赞赏1元钱的支持。这个金额不会对您的财务状况造成负担,但它会对我继续创作高质量的内容产生积极的影响。
我之所以写这篇文章,是因为我热爱分享有用的知识和见解。您的支持将帮助我继续这个使命,也鼓励我花更多的时间和精力创作更多有价值的内容。
如果您愿意支持我的创作,请扫描下面二维码,您的支持将不胜感激。同时,如果您有任何反馈或建议,也欢迎与我分享。
![在这里插入图片描述](https://img-blog.csdnimg.cn/e06a317e89694a23ad89d2c59538c3a1.jpeg#pic_center =450x300)
再次感谢您的阅读和支持!
最诚挚的问候, “愚公搬代码”
- 点赞
- 收藏
- 关注作者
评论(0)