VB.NET 绘图教程

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

vb.net 绘图教程
(图片来源网络,侵删)

核心概念

在开始绘图之前,你需要理解几个核心概念:

  1. 画布 - Graphics 对象

    • Graphics 类是所有绘图操作的核心,它代表一个绘图表面(画布),比如一个窗体、一个图片控件或一个内存中的位图。
    • 你不能直接创建 Graphics 对象,而是必须从已有的对象(如窗体或控件)中“获取”它,最常用的方法是重写控件的 OnPaint 事件,并通过 e.Graphics 参数来获取。
  2. 画笔 - Pen 对象

    • Pen 类用于绘制线条、曲线和图形的轮廓。
    • 你可以指定画笔的颜色 (Color)、宽度 (Width)、线型(实线、虚线等)等属性。
  3. 画刷 - Brush 对象

    vb.net 绘图教程
    (图片来源网络,侵删)
    • Brush 类用于填充图形的内部区域(如矩形、圆形、多边形等)。
    • Brush 是一个抽象基类,常用的子类有:
      • SolidBrush: 单色画刷。
      • LinearGradientBrush: 线性渐变画刷。
      • TextureBrush: 使用图片作为纹理的画刷。
  4. 图形 - 各种形状类

    • Rectangle, RectangleF: 表示矩形。
    • Circle: 没有专门的 Circle 类,通常使用 Ellipse 来画圆,它需要一个 Rectangle 对象来定义其边界。
    • Point, PointF: 表示一个点。
    • Size, SizeF: 表示一个尺寸。
  5. 坐标系统

    • 默认情况下,坐标原点 (0, 0) 位于画布的左上角。
    • X 轴向右递增,Y 轴向下递增。
    • 所有绘图单位都是像素。

第一个绘图程序:在窗体上画一条线

让我们从一个最简单的例子开始:创建一个 Windows 窗体应用程序,并在窗体上画一条蓝色的直线。

步骤 1:创建项目

vb.net 绘图教程
(图片来源网络,侵删)
  1. 打开 Visual Studio。
  2. 创建一个新项目,选择 "Windows 窗体应用" (.NET Framework 或 .NET)。
  3. 给项目命名,VBNetDrawingDemo

步骤 2:编写绘图代码

  1. 在设计视图中,双击窗体(Form1),自动生成 Form1_Load 事件,虽然我们也可以在这里绘图,但更好的做法是使用 Paint 事件,因为它在窗体首次显示、被遮挡后重新显示等情况下都会被触发,能确保图形正确显示。

  2. 在解决方案资源管理器中,右键点击你的窗体文件(如 Form1.vb),选择“查看代码”。

  3. 在代码编辑器顶部,从左侧的下拉菜单选择 (Form1 Events),从右侧的下拉菜单选择 Paint 事件,这会自动为你创建 Form1_Paint 事件处理程序。

  4. 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,你的绘图操作就会变得平滑很多。


完整示例:一个简单的绘图板

让我们结合所学知识,创建一个简单的绘图板,允许用户用鼠标在窗体上画线。

  1. 创建项目:同上。
  2. 窗体设计
    • 在窗体上添加一个 Button,将其 Text 属性设置为“清除”。
    • 将窗体的 Text 属性设置为“我的绘图板”。
  3. 编写代码
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

这个简单绘图板可以直接运行,你可以在窗体上按住鼠标左键并拖动来画线,点击“清除”按钮,画布会被清空。


总结与学习建议

  1. 掌握核心三要素Graphics (画布), Pen (画笔), Brush (画刷) 是你绘图世界的基石。
  2. 善用 Paint 事件:对于需要持久化显示的图形,始终在 Paint 事件中绘制。
  3. 从简单开始:先画线、画矩形,再逐步尝试更复杂的图形和效果。
  4. 探索命名空间System.DrawingSystem.Drawing.Drawing2D 中还有更多强大的类等你去探索,Bitmap, Icon, FontFamily, Region 等。
  5. 实践出真知:尝试修改颜色、大小、位置,组合不同的图形,创造出你自己的作品。

希望这份教程对你有帮助!祝你学习愉快!