VB.NET 绘图教程
在 VB.NET 中,绘图主要通过 System.Drawing 命名空间下的类来实现,这个命名空间提供了丰富的功能,让你能够在窗体、图片、打印机等各种表面上绘制图形。

核心概念
在开始绘图之前,你需要理解几个核心概念:
-
画布 -
Graphics对象Graphics类是所有绘图操作的核心,它代表一个绘图表面(画布),比如一个窗体、一个图片控件或一个内存中的位图。- 你不能直接创建
Graphics对象,而是必须从已有的对象(如窗体或控件)中“获取”它,最常用的方法是重写控件的OnPaint事件,并通过e.Graphics参数来获取。
-
画笔 -
Pen对象Pen类用于绘制线条、曲线和图形的轮廓。- 你可以指定画笔的颜色 (
Color)、宽度 (Width)、线型(实线、虚线等)等属性。
-
画刷 -
Brush对象
(图片来源网络,侵删)Brush类用于填充图形的内部区域(如矩形、圆形、多边形等)。Brush是一个抽象基类,常用的子类有:SolidBrush: 单色画刷。LinearGradientBrush: 线性渐变画刷。TextureBrush: 使用图片作为纹理的画刷。
-
图形 - 各种形状类
Rectangle,RectangleF: 表示矩形。Circle: 没有专门的Circle类,通常使用Ellipse来画圆,它需要一个Rectangle对象来定义其边界。Point,PointF: 表示一个点。Size,SizeF: 表示一个尺寸。
-
坐标系统
- 默认情况下,坐标原点 (0, 0) 位于画布的左上角。
- X 轴向右递增,Y 轴向下递增。
- 所有绘图单位都是像素。
第一个绘图程序:在窗体上画一条线
让我们从一个最简单的例子开始:创建一个 Windows 窗体应用程序,并在窗体上画一条蓝色的直线。
步骤 1:创建项目

- 打开 Visual Studio。
- 创建一个新项目,选择 "Windows 窗体应用" (.NET Framework 或 .NET)。
- 给项目命名,
VBNetDrawingDemo。
步骤 2:编写绘图代码
-
在设计视图中,双击窗体(
Form1),自动生成Form1_Load事件,虽然我们也可以在这里绘图,但更好的做法是使用Paint事件,因为它在窗体首次显示、被遮挡后重新显示等情况下都会被触发,能确保图形正确显示。 -
在解决方案资源管理器中,右键点击你的窗体文件(如
Form1.vb),选择“查看代码”。 -
在代码编辑器顶部,从左侧的下拉菜单选择
(Form1 Events),从右侧的下拉菜单选择Paint事件,这会自动为你创建Form1_Paint事件处理程序。 -
在
Form1_Paint事件中输入以下代码:
' 导入 System.Drawing 命名空间,这样就不需要每次都写完整的类名了
Imports System.Drawing
Imports System.Drawing.Drawing2D ' 导入高级绘图功能
Public Class Form1
' Form1_Paint 事件在窗体需要重绘时触发(窗口被移动后)
Private Sub Form1_Paint(sender As Object, e As PaintEventArgs) Handles MyBase.Paint
' 1. 获取画布对象 (Graphics)
' e.Graphics 就是我们要操作的画布
Dim g As Graphics = e.Graphics
' 2. 创建画笔对象 (Pen)
' 创建一个蓝色、宽度为3的画笔
Dim myPen As New Pen(Color.Blue, 3)
' 3. 绘制线条
' DrawLine 方法需要两个点:起点和终点
' Point.X, Point.Y
g.DrawLine(myPen, 50, 50, 300, 200)
' 4. (可选) 释放资源
' 虽然 .NET 有垃圾回收机制,但显式释放非托管资源(如 Pen, Brush, Bitmap)是好习惯
myPen.Dispose()
g.Dispose() ' 注意:通常不需要释放 e.Graphics,因为它由系统管理
End Sub
End Class
步骤 3:运行程序
按 F5 运行项目,你会看到一个窗体,上面有一条从左上角附近到右下角附近的蓝色直线。
绘制更多图形
现在我们知道了基本流程,可以尝试绘制更多图形。
绘制矩形和填充
Private Sub Form1_Paint(sender As Object, e As PaintEventArgs) Handles MyBase.Paint
Dim g As Graphics = e.Graphics
' 绘制一个空心矩形
Dim blackPen As New Pen(Color.Black, 2)
g.DrawRectangle(blackPen, 50, 50, 150, 100) ' (x, y, width, height)
' 绘制一个填充的红色矩形
Dim redBrush As New SolidBrush(Color.Red)
g.FillRectangle(redBrush, 250, 50, 150, 100)
' 释放资源
blackPen.Dispose()
redBrush.Dispose()
End Sub
绘制圆形(椭圆)
Private Sub Form1_Paint(sender As Object, e As PaintEventArgs) Handles MyBase.Paint
Dim g As Graphics = e.Graphics
' 绘制一个空心圆
' 圆是一个特殊的椭圆,其宽度和高度相等
Dim greenPen As New Pen(Color.Green, 3)
g.DrawEllipse(greenPen, 50, 200, 120, 120) ' 定义一个正方形区域,DrawEllipse会画一个内切圆
' 绘制一个填充的黄色椭圆
Dim yellowBrush As New SolidBrush(Color.Yellow)
g.FillEllipse(yellowBrush, 250, 200, 150, 80) ' 定义一个椭圆区域
greenPen.Dispose()
yellowBrush.Dispose()
End Sub
绘制弧线和扇形
Private Sub Form1_Paint(sender As Object, e As PaintEventArgs) Handles MyBase.Paint
Dim g As Graphics = e.Graphics
' 绘制弧线
Dim purplePen As New Pen(Color.Purple, 5)
' DrawArc(pen, x, y, width, height, startAngle, sweepAngle)
' startAngle: 起始角度(度数)
' sweepAngle: 扫过的角度(度数)
g.DrawArc(purplePen, 50, 350, 150, 150, 0, 180) ' 画一个半圆弧
' 绘制扇形
Dim cyanBrush As New SolidBrush(Color.Cyan)
' FillPie(brush, x, y, width, height, startAngle, sweepAngle)
g.FillPie(cyanBrush, 250, 350, 150, 150, 45, 90) ' 从45度开始,画一个90度的扇形
purplePen.Dispose()
cyanBrush.Dispose()
End Sub
高级绘图技巧
使用路径绘制复杂图形
GraphicsPath 允许你将多个图形(如直线、曲线、矩形、圆)组合成一个单一的路径对象,然后一次性绘制或填充它。
Private Sub Form1_Paint(sender As Object, e As PaintEventArgs) Handles MyBase.Paint
Dim g As Graphics = e.Graphics
' 创建一个路径
Dim myPath As New GraphicsPath()
' 向路径中添加图形
myPath.AddLine(50, 50, 150, 150)
myPath.AddLine(150, 150, 250, 50)
myPath.AddEllipse(50, 200, 200, 100) ' 在路径中添加一个椭圆
' 创建画笔和画刷
Dim pathPen As New Pen(Color.Orange, 3)
Dim pathBrush As New SolidBrush(Color.LightPink)
' 绘制路径的轮廓
g.DrawPath(pathPen, myPath)
' 填充路径
g.FillPath(pathBrush, myPath)
' 释放资源
myPath.Dispose()
pathPen.Dispose()
pathBrush.Dispose()
End Sub
绘制文本
使用 DrawString 方法可以在画布上绘制文本。
Private Sub Form1_Paint(sender As Object, e As PaintEventArgs) Handles MyBase.Paint
Dim g As Graphics = e.Graphics
' 创建字体和画刷
Dim myFont As New Font("微软雅黑", 24, FontStyle.Bold) ' 字体、大小、样式
Dim textBrush As New SolidBrush(Color.DarkBlue)
' DrawString(text, font, brush, x, y)
g.DrawString("你好,VB.NET 绘图世界!", myFont, textBrush, 50, 50)
myFont.Dispose()
textBrush.Dispose()
End Sub
图像处理
你可以将图片加载到 Bitmap 对象中,然后使用 DrawImage 方法将其绘制到画布上。
Private Sub Form1_Paint(sender As Object, e As PaintEventArgs) Handles MyBase.Paint
Dim g As Graphics = e.Graphics
' 加载图片
' 假设你有一个名为 "myimage.jpg" 的图片放在项目根目录,并设置为"如果较新则复制"
Dim myImage As Bitmap = Image.FromFile("myimage.jpg")
' 在指定位置绘制图片
g.DrawImage(myImage, 50, 50)
' 释放资源
myImage.Dispose()
End Sub
双缓冲技术
当你在窗体上进行频繁或复杂的绘图时,可能会出现闪烁现象,这是因为绘图是直接在屏幕上进行的,重绘过程对用户是可见的。
双缓冲是一种通过在内存中先完成所有绘图,然后将最终一次性绘制到屏幕上的技术,可以有效消除闪烁。
在 VB.NET 中,启用双缓冲非常简单,只需在窗体的构造函数中设置一个属性即可。
Public Class Form1
Public Sub New()
' 此调用是 Windows 窗体设计器所必需的。
InitializeComponent()
' 启用双缓冲
Me.DoubleBuffered = True
' 或者,对于整个应用程序的所有控件启用双缓冲(更高级的做法)
' SetStyle(ControlStyles.OptimizedDoubleBuffer, True)
' SetStyle(ControlStyles.AllPaintingInWmPaint, True)
' SetStyle(ControlStyles.UserPaint, True)
End Sub
' ... 你的 Paint 事件代码 ...
End Class
只需添加 Me.DoubleBuffered = True,你的绘图操作就会变得平滑很多。
完整示例:一个简单的绘图板
让我们结合所学知识,创建一个简单的绘图板,允许用户用鼠标在窗体上画线。
- 创建项目:同上。
- 窗体设计:
- 在窗体上添加一个
Button,将其Text属性设置为“清除”。 - 将窗体的
Text属性设置为“我的绘图板”。
- 在窗体上添加一个
- 编写代码:
Imports System.Drawing
Imports System.Windows.Forms
Public Class Form1
' 声明一个变量来记录用户是否正在拖动鼠标
Private isDrawing As Boolean = False
' 声明一个变量来存储上一次的鼠标坐标
Private lastPoint As Point
Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
' 启用双缓冲以防止绘图时闪烁
Me.DoubleBuffered = True
End Sub
' 当鼠标按下时,开始绘图
Private Sub Form1_MouseDown(sender As Object, e As MouseEventArgs) Handles MyBase.MouseDown
isDrawing = True
' 记录当前鼠标位置作为线条的起点
lastPoint = e.Location
End Sub
' 当鼠标移动时,如果正在绘图,则画线
Private Sub Form1_MouseMove(sender As Object, e As MouseEventArgs) Handles MyBase.MouseMove
If isDrawing Then
' 获取画布
Dim g As Graphics = Me.CreateGraphics() ' 直接在窗体上绘制
' 创建画笔
Dim myPen As New Pen(Color.Black, 2)
' 从上一点画到当前点
g.DrawLine(myPen, lastPoint, e.Location)
' 更新“上一次”的坐标
lastPoint = e.Location
' 释放资源
myPen.Dispose()
' 注意:这里我们不释放 g,因为它是临时创建的,CreateGraphics() 返回的 Graphics 对
' 应不应被缓存或长期持有,每次鼠标移动都调用 CreateGraphics() 虽然简单,但效率
' 不高,更好的做法是只在 Paint 事件中绘制,并记录所有线条点,然后在 Paint 事件中重绘所有线条。
' 但对于这个简单示例,这样写更直观。
End If
End Sub
' 当鼠标松开时,结束绘图
Private Sub Form1_MouseUp(sender As Object, e As MouseEventArgs) Handles MyBase.MouseUp
isDrawing = False
End Sub
' “清除”按钮的点击事件
Private Sub btnClear_Click(sender As Object, e As EventArgs) Handles btnClear.Click
' 获取窗体的整个区域
Dim clientRect As New Rectangle(Me.ClientRectangle.X, Me.ClientRectangle.Y, Me.ClientRectangle.Width, Me.ClientRectangle.Height)
' 创建一个与窗体背景色相同的画刷来“清除”绘图区域
' 更简单的方法是强制窗体重绘,清除它会自动清除所有自定义绘图
Me.Invalidate() ' Invalidate() 方法会告诉系统窗体需要重绘,从而触发 Paint 事件
End Sub
' 重写 OnPaint 方法,以便在需要时(如调用 Invalidate() 后)重绘窗体
' 注意:这个例子中我们没有在这里画线,而是直接在 MouseMove 中画了。
' 一个更健壮的绘图板会在这里实现重绘逻辑。
Protected Overrides Sub OnPaint(e As PaintEventArgs)
' 调用基类的 OnPaint 方法
MyBase.OnPaint(e)
' 在这里可以添加需要在每次重绘时都出现的图形
End Sub
End Class
这个简单绘图板可以直接运行,你可以在窗体上按住鼠标左键并拖动来画线,点击“清除”按钮,画布会被清空。
总结与学习建议
- 掌握核心三要素:
Graphics(画布),Pen(画笔),Brush(画刷) 是你绘图世界的基石。 - 善用 Paint 事件:对于需要持久化显示的图形,始终在
Paint事件中绘制。 - 从简单开始:先画线、画矩形,再逐步尝试更复杂的图形和效果。
- 探索命名空间:
System.Drawing和System.Drawing.Drawing2D中还有更多强大的类等你去探索,Bitmap,Icon,FontFamily,Region等。 - 实践出真知:尝试修改颜色、大小、位置,组合不同的图形,创造出你自己的作品。
希望这份教程对你有帮助!祝你学习愉快!
