用 C# picturebox 控件画图

【日志】
2019/7/18
今天介绍一下 C# 用 picturebox 画坐标系
2020/6/13
这篇文章是在去年发的,没想到帮助了很多朋友。这段时间又用到 PictureBox 控件绘图了,觉得有必要把自己最近学到的补充一下,分享给大家,所以下面来个补充好了(之前的 虽然很low 但是就不删了,毕竟也是满满的回忆,嘿嘿)

一、19/7/18版本

编译环境:VS2010
1.首先建立一个 Windows窗体应用程序 如下图1所示

图1
建好后,就会出现一个窗体设计界面,可以在属性栏更改其名字,图标,Text……如下图2所示:
图2
2.添加控件 “picturebox” 和 “button” 如图3所示(可根据需要更改名字):
图3
3.双击 “绘图” 按钮添加事件响应函数;
在此之前,首先要明白如何从绘图坐标系转换为我们常用的坐标系,如下图3所示:
黑色的是绘图坐标系,红色的是我们常用的坐标系,简单画下图就可得到图中所示公式
图3
本来想画个写轮眼,可最后成了下图4的样子(笑哭):

图4
要画好看一点要仔细研究点在哪里,这里就简单介绍一下在 picturebox 中怎样画线,画椭圆,“绘图按钮”点击函数中有:

private void button1_Click(object sender, EventArgs e)
        {
            Graphics g1 = pictureBox1.CreateGraphics();//画布
            g1.Clear(Color.White);
            Pen p = new Pen(Color.Red, 2);//画笔
            Pen p1 = new Pen(Color.Black, 2);
            Pen p2 = new Pen(Color.Brown, 5);
            Pen p3 = new Pen(Color.Black, 20);
            Font f = new Font("宋体", 10);//字体
            int a = pictureBox1.Size.Height;
            int b = pictureBox1.Size.Width;
            g1.DrawLine(p1, 0, a, 0, 0);//画线
            g1.DrawLine(p1, 0, a, b, a);
            g1.DrawLine(p1, 0, 0, 5, 10);
            g1.DrawLine(p1, b, a, b - 10, a - 5);
            g1.DrawString("O", f, Brushes.Black, 3, a - 20);
            g1.DrawString("正北X", f, Brushes.Black, 3, 3);
            g1.DrawString("正东Y", f, Brushes.Black, b - 50, a - 20);

            Point1[] Pt=new Point1[20];
            Point1[] Pt1 = new Point1[20];
            Pt[0] = new Point1("0", 400, 200);
            Pt[1] = new Point1("1", 250, 250);
            Pt[2] = new Point1("2", 200, 400);
            Pt[3] = new Point1("3", 150, 250);
            Pt[4] = new Point1("4", 0, 200);
            Pt[5] = new Point1("5", 150, 150);
            Pt[6] = new Point1("6", 200, 0);
            Pt[7] = new Point1("7", 250, 150);
            Pt[9] = new Point1("8",200,a-200);
            int i = 0;
            for (i = 0; i < 8; i++)
            {
                Pt1[i] = new Point1(Pt[i].name, Pt[i].y, a - Pt[i].x);
            }
            g1.FillEllipse(Brushes.Black, Pt[9].x-200, Pt[9].y-200, 400, 400);
            g1.FillEllipse(Brushes.Red, Pt[9].x - 170, Pt[9].y - 170, 340, 340);
            g1.FillEllipse(Brushes.Brown, Pt[9].x - 120, Pt[9].y - 120, 240, 240);
            g1.FillEllipse(Brushes.Red, Pt[9].x - 105, Pt[9].y - 105, 210, 210);
            g1.FillEllipse(Brushes.Black, Pt[9].x - 80, Pt[9].y - 80, 160, 160);
            g1.FillEllipse(Brushes.Red, Pt[9].x - 65, Pt[9].y - 65, 130, 130);
            g1.FillEllipse(Brushes.Black, Pt[9].x - 25, Pt[9].y - 25, 50, 50);
            i = 0;
            while (Pt1[i + 1] != null)
            {
                g1.DrawLine(p2, Pt1[i].x, Pt1[i].y, Pt1[i + 1].x, Pt1[i + 1].y);
                i++;
            }
            g1.DrawLine(p2, Pt1[0].x, Pt1[0].y, Pt1[i].x, Pt1[i].y);
            i = 1;
            while (i<=7)
            {
                g1.FillEllipse(Brushes.Black, Pt1[i].x - 25, Pt1[i].y - 25, 60, 60);
                g1.FillEllipse(Brushes.Red, Pt1[i].x - 20, Pt1[i].y - 20, 40, 40);
                
                //g1.DrawString(Pt1[i].name, f, Brushes.Black, Pt1[i].x - 5, Pt1[i].y + 5);
                i=i+2;
            }
            g1.DrawLine(p3, Pt1[0].x, Pt1[0].y, 200, a-280);
            g1.DrawLine(p3, Pt1[2].x, Pt1[2].y, 280, a - 200);
            g1.DrawLine(p3, Pt1[4].x, Pt1[4].y, 200, a - 120);
            g1.DrawLine(p3, Pt1[6].x, Pt1[6].y, 120, a - 200);
            g1.Dispose();
        }

4.双击“清空画布”按钮,添加响应事件:

private void button2_Click(object sender, EventArgs e)
        {
            Graphics g = pictureBox1.CreateGraphics();
            g.Clear(Color.White);
        }

点击运行,OK!

二、20/6/13版本

还是用的 VS2010,首先说明一点,不论是在PictureBox 上画图,还是在窗体上直接画,都要用到 Graphics,个人感觉他们是一样的,不信我们下面我们一起来看。
1.首先新建个窗体,在加一个pictureBox:
在这里插入图片描述
名字啥的随便区,但是要拉的大一点(不然一会画不下)可见我拉的很长,pictureBox (我取名为pB)占据了右边半壁江山

2.添加 Paint 响应事件:
在这里插入图片描述
同样为pB 添加Paint 响应事件:

		private void Draft_Paint(object sender, PaintEventArgs e)
        {

        }

        private void pB_Paint(object sender, PaintEventArgs e)
        {

        }

下面我们要做的就是在这俩Paint 里面码代码画东西了。这样,我先简单介绍一下 Graphics 里面画图的方法有哪些,之后再来画个“全景图”。
在这里插入图片描述
我觉得我下面介绍的东西应该叫“对Graphics类的介绍”,PictureBox 也好,窗体也好,我们想在上面画图都得用:Graphics g = e.Graphics;其中e为:PaintEventArgs e 是由上面的Paint 事件搞出来的。所以:

Graphics 的属性和方法有很多,可以看看:

MSDN:https://docs.microsoft.com/zh-cn/dotnet/api/system.drawing.graphics?view=netcore-3.1

本来想截个长图放这里的,可是那实在是太长辽,朋友们可以自己去读一读。这里就简单介绍几个常用的绘图方法吧

1.预备知识

1.1 Color
public struct Color : IEquatable<System.Drawing.Color>

表示一种 ARGB 颜色(alpha、红色、绿色、蓝色)。
每个像素的颜色表示为32位数字:8位,分别用于 alpha、红色、绿色和蓝色(ARGB)。 这四个组件都是0到255之间的一个数字,0表示没有强度,255表示完全强度。 Alpha 分量指定颜色的透明度:0表示完全透明,255表示完全不透明。 若要确定颜色的 alpha、红色、绿色或蓝色分量,请分别使用 A、R、G或 B 属性。 您可以通过使用其中一个 FromArgb 方法来创建自定义颜色。

系统自带了好多颜色:

https://docs.microsoft.com/zh-cn/dotnet/api/system.drawing.color?view=netcore-3.1

1.2 GraphicsPath
public sealed class GraphicsPath : MarshalByRefObject, ICloneable, IDisposable

表示一系列相互连接的直线和曲线。 无法继承此类。
详见:(目前看不懂)

https://docs.microsoft.com/zh-cn/dotnet/api/system.drawing.drawing2d.graphicspath?view=netcore-3.1

1.3 Single
public struct Single : IComparable, IComparable<float>, IConvertible, IEquatable<float>, IFormattable

表示单精度浮点数。
Single 值类型表示单精度32位数字,其值范围从负 3.402823 e 38 到正 3.402823 e 38,以及正或负零、PositiveInfinity、NegativeInfinity,而不是数字(NaN)。 它用于表示非常大的值(例如行星或 galaxies 之间的距离)或极小的值(例如物质的分子质量,以千克为间隔),并且通常不精确(如从地球到另一颗太阳系的距离)。 Single 类型符合二元浮点算术的 IEC 60559:1989 (IEEE 754)标准。

2.一些方法简介

1.清除整个绘图面并以指定背景色填充。
public void Clear (System.Drawing.Color color);

2.释放此 Graphics 使用的所有资源。
public void Dispose ();//前面这俩应该是绘图必用的

3.绘制一段弧线,它表示由一对坐标、宽度和高度指定的椭圆部分。
DrawArc //有四个重载,吐槽一下,和我的脑回路很不同,很费解,可以看看我之前写的一篇博客(链接见下)

4.绘制由 4 个 Point 结构定义的贝塞尔样条。
DrawBezier(Pen, Point, Point, Point, Point);//3重载,挺高大上的,目前没用过

5.绘制由 Point 结构的数组定义的闭合基数样条。
DrawClosedCurve(Pen, Point[], Single, FillMode)

6.绘制经过一组指定的 Point 结构的基数样条。
DrawCurve(Pen, Point[])

7.绘制一个由边框(该边框由一对坐标、高度和宽度指定)定义的椭圆。
DrawEllipse(Pen, Rectangle)

8.在指定坐标处绘制由指定的 Icon 表示的图像。
DrawIcon(Icon, Int32, Int32)

9.在指定位置并且按原始大小绘制指定的 Image。
DrawImage

10.绘制一条连接由坐标对指定的两个点的线条。
DrawLine(Pen, PointF, PointF)

11.绘制一系列连接一组 Point 结构的线段。
DrawLines(Pen, PointF[])

12.绘制 GraphicsPath。
public void DrawPath (System.Drawing.Pen pen, System.Drawing.Drawing2D.GraphicsPath path);

13.绘制一个扇形,该形状由一个坐标对、宽度、高度以及两条射线所指定的椭圆定义。
DrawPie(Pen, Single, Single, Single, Single, Single, Single)

14.绘制由一组 Point 结构定义的多边形。
DrawPolygon(Pen, PointF[])

15.绘制由坐标对、宽度和高度指定的矩形。
DrawRectangle(Pen, Single, Single, Single, Single)

16.绘制一系列由 Rectangle 结构指定的矩形。
DrawRectangles(Pen, Rectangle[])

17.在指定位置并且用指定的 Brush 和 Font 对象绘制指定的文本字符串。
DrawString(String, Font, Brush, Single, Single, StringFormat)

18.填充边框所定义的椭圆的内部,该边框由一对坐标、一个宽度和一个高度指定。
FillEllipse(Brush, Single, Single, Single, Single)

19.填充由一对坐标、一个宽度、一个高度以及两条射线指定的椭圆所定义的扇形区的内部。
FillPie(Brush, Single, Single, Single, Single, Single, Single)

20.填充 Point 结构指定的点数组所定义的多边形的内部。
FillPolygon(Brush, PointF[])

21.填充由一对坐标、一个宽度和一个高度指定的矩形的内部。
FillRectangle(Brush, Rectangle)

22.填充 Region 的内部。
public void FillRegion (System.Drawing.Brush brush, System.Drawing.Region region);

23.测量用指定的 Font 绘制的指定字符串。
MeasureString(String, Font)

DrawArc :https://blog.csdn.net/Gou_Hailong/article/details/106715943

3.使用示例

将这些代码贴到Paint 函数中

			Graphics g = e.Graphics;
            g.Clear(Color.White);//1
            PointF[] pt = new PointF[4];
            pt[0] = new PointF(50, 50);
            pt[1] = new PointF(50, 100);
            pt[2] = new PointF(70, 110);
            pt[3] = new PointF(100, 100);
            // create pen.
            Pen p = new Pen(Color.Blue, 2);
            g.DrawBezier(p, pt[0], pt[1], pt[2], pt[3]);//4
            for (int i = 0; i < 4; i++)
            { pt[i].Y += 60;}
            g.DrawClosedCurve(p, pt);//5
            for (int i = 0; i < 4; i++)
            { pt[i].Y += 60; }
            g.DrawCurve(p, pt);//6
            
            g.DrawEllipse(p, 100, 100, 60, 100);//7
            for (int i = 0; i < 4; i++)
            { pt[i].Y += 60; }
            g.DrawLine(p, pt[1], pt[3]);//10
            for (int i = 0; i < 4; i++)
            { pt[i].Y += 60; }
            g.DrawPie(p, pt[0].X, pt[0].Y, 60, 50, 60, 250);//13
            for (int i = 0; i < 4; i++)
            { pt[i].Y += 60; }
            g.DrawPolygon(p, pt);//14
            p.Color = Color.Yellow;
            for (int i = 0; i < 4; i++)
            { pt[i].Y -= 60 * 5; pt[i].X += 60; }
            g.DrawRectangle(p, pt[3].X, pt[3].Y, 100, 50);//15
            for (int i = 0; i < 4; i++)
            {  pt[i].X += 60; }
            Font f = new Font("宋体", 15);
            Brush b = Brushes.Cyan;
            g.DrawString("Stay Hungry", f, b, pt[2]);//17
            b = Brushes.DarkOrange;
            for (int i = 0; i < 4; i++)
            { pt[i].X += 60; }
            g.FillEllipse(b, pt[1].X, pt[1].Y, 20, 20);//18
            for (int i = 0; i < 4; i++)
            { pt[i].Y += 60; }
            g.FillPie(b, pt[3].X, pt[3].Y, 60, 50, 60, 250);//19
            for (int i = 0; i < 4; i++)
            { pt[i].Y += 60; }
            g.FillPolygon(b, pt);//20
            for (int i = 0; i < 4; i++)
            { pt[i].Y += 60; }
            g.FillRectangle(b, pt[3].X, pt[3].Y, 100, 50);//21
            g.Dispose();//2

结果:
在这里插入图片描述

4.问题

当我将上面的代码贴到pB_Paint 中时,之后出现问题:
在这里插入图片描述
按理说应该没啥问题,目前解决不了,到时候来填坑。

参考

https://docs.microsoft.com/zh-cn/dotnet/api/system.drawing.graphics?view=netcore-3.1

### 回答1: 可以使用C#中的Graphics类,在PictureBox控件上绘制图形。具体步骤如下: 1. 在PictureBox控件的Paint事件中获取Graphics对象: private void pictureBox1_Paint(object sender, PaintEventArgs e) { Graphics g = e.Graphics; } 2. 使用Graphics对象的各种绘图方法绘制图形,例如绘制直线: g.DrawLine(Pens.Black, , , 100, 100); 3. 在需要更新PictureBox控件时,调用其Invalidate方法触发Paint事件重新绘制图形: pictureBox1.Invalidate(); 完整的示例代码如下: private void pictureBox1_Paint(object sender, PaintEventArgs e) { Graphics g = e.Graphics; g.DrawLine(Pens.Black, , , 100, 100); } private void button1_Click(object sender, EventArgs e) { pictureBox1.Invalidate(); } ### 回答2: 对不起,无法回答没有上下文或足够信息的简短问题“c”是什么。请提供更多信息以便我可以帮您回答问题。 ### 回答3: C是一种流行的编程语言,也是最初由贝尔实验室的丹尼斯·里奇和肯·汤普森开发出来的语言。它有许多特点,包括易于学习、可移植性和高效性等。C语言的设计使它成为编写系统软件和应用程序的理想选择,从操作系统到浏览器,从数据库到游戏,C语言贡献卓著。 C语言的编写有许多的好处。首先,它能够快速地编写程序,这是由于它的语法简单,易于读写。其次,C语言可以跨平台,能够在任何计算机上运行,包括Windows、Linux、Unix等。另外,C语言支持能够直接访问硬件的低级操作,这对于性能和速度非常重要。 尽管C语言拥有如此多的优点,但它也有一些缺点。比如,C语言需要程序员负责管理内存分配,这就容易导致内存泄露和内存溢出等问题。此外,C语言的开发速度通常会比其他语言慢,因为程序员需要编写非常详细的代码。 总的来说,C语言是一门非常重要的编程语言。它在许多领域中广泛应用,包括操作系统、数据库、游戏、网络和应用程序等。尽管它有一些缺点,但其优点远远超过了缺点,使得它在程序员和软件开发者中仍然非常流行。
评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

流浪猪头拯救地球

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值