首页 > 解决方案 > 我可以画的网格

问题描述

所以我正在尝试创建一个应用程序来简化像素艺术(学校项目)的创建,到目前为止我所做的是在面板中绘制一个网格,下一步是允许用户单击一个单元格并拥有它画了,但我无法让它工作,这是我的代码:

Private Sub drawGrid(g As Graphics, rows As Integer, columns As Integer)

    Dim originPoint As Point = New Point(10, 2)
    Dim size As Size = New Size(64, 64)
    Dim left As Integer = originPoint.X
    Dim up As Integer = originPoint.Y
    Dim right As Integer = originPoint.X + (columns * size.Width)
    Dim down As Integer = originPoint.Y + (rows * size.Height)
    For y As Integer = up To down + 1 Step size.Height
        Dim pt1 As New Point(left, y)
        Dim pt2 As New Point(right, y)
        g.DrawLine(Pens.Black, pt1, pt2)
    Next
    For x As Integer = left To right + 1 Step size.Width
        Dim pt1 As New Point(x, up)
        Dim pt2 As New Point(x, down)
        g.DrawLine(Pens.Black, pt1, pt2)
    Next

End Sub

这会绘制一个包含用户想要的列数和行数的网格,但我一直在努力允许绘画

我一直在想的是:处理此代码,并创建一个“像素”类,根据用户行和列创建“像素”对象的数量,并单独绘制每个对象,然后只需更改每个“像素”的颜色

标签: vb.net

解决方案


这是一个Grid允许设置其单元格颜色的类。

使用.Grid引用单元格List(Of List(Of Class))

CellObject 类包含一个简单的属性Rectagle,用于测量单元格的大小,以及一个Color允许设置单个单元格颜色的属性:

Friend Class GridCell
    Public Property Cell() As Rectangle
    Public Property CellColor() As Color
End Class

您可以定义:

  • 网格大小 →ColoredGrid.GridSize = new Size(...)
  • 列数和行数 →ColoredGrid.GridColumnsRows = new Size(...)
  • 网格在Canvas内的位置→ColoredGrid.GridPosition = New Point(...)
  • 网格的颜色 →ColoredGrid.GridColor = Color.Gray
  • 单元格的背景颜色 →ColoredGrid.CellColor = Color.FromArgb(32, 32, 32)
  • 选定单元格的颜色 →ColoredGrid.SelectedCellColor = Color.OrangeRed


该类Grid包含对控件的引用,该控件将用作网格绘制的Canvas。此引用在类构造函数中设置。注册Canvas控件和事件
以自动响应相关操作。 当在Canvas表面上检测到鼠标单击时,该属性会报告单击发生的坐标。GridPaint()MouseClick()
MouseEventArgs e.Location

为了识别Grid Cell执行此操作的位置,该GetUpdateCell()方法List(Of List(Of GridCell))使用一个简单LINQ SelectMany()且已识别的Cell包含鼠标单击坐标(表示为Point()值)的矩形来检查。
执行此识别时只需检查 Cell Rectangle.Contains(Point())是否。
识别单元格后,调用Canvas Invalidate()方法,指定要重新绘制的区域。
该区域对应于Cell Rectangle,因此在 a 着色时仅重绘该部分Cell,以节省资源和时间。

要对其进行测试,请在 a 中创建 aPanelButtona Form

Imports System.Drawing

'This Grid object in defined at Form Class scope 
Public ColoredGrid As ColorGrid

'Button used to trigger the Grid painting
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
    If ColoredGrid IsNot Nothing Then
        ColoredGrid.Dispose()
    End If
    ColoredGrid = New ColorGrid(Panel1)
    ColoredGrid.GridSize = New Size(300, 300)
    ColoredGrid.GridColumnsRows = New Size(10, 10)
    ColoredGrid.GridPosition = New Point(10, 10)
    ColoredGrid.GridColor = Color.White
    ColoredGrid.CellColor = Color.FromArgb(32, 32, 32)
    ColoredGrid.SelectedCellColor = Color.OrangeRed
    ColoredGrid.BuildGrid()
End Sub

这是一个可视化示例,展示了它是如何工作的:

在此处输入图像描述

这是主要的 Grid 类。
该类ColorGrid支持IDisposable,因为它注册了所描述的事件。当不再使用该类时,这些必须取消注册。如果你不这样做,可能会发生奇怪的事情。

Public Class ColorGrid
    Implements IDisposable

    Private Grid As List(Of List(Of GridCell))
    Private CurrentGridSize As New Size(100, 100)
    Private GridColRows As New Size(10, 10)
    Private CellSize As New Size(10, 10)
    Private MouseCell As Point = Point.Empty
    Private Canvas As Control = Nothing
    Private UpdateCell As Boolean = False
    Private NewGrid As Boolean = False

    Public Sub New(DrawingControl As Control)
        If DrawingControl IsNot Nothing Then
            Me.Canvas = DrawingControl
            AddHandler Me.Canvas.Paint, New PaintEventHandler(AddressOf Me.ControlPaint)
            AddHandler Me.Canvas.MouseClick, New MouseEventHandler(AddressOf Me.MouseHandler)
            Me.GridPosition = New Point(10, 10)
            Me.CellColor = Color.FromArgb(32, 32, 32)
        End If
    End Sub

    Public Property GridPosition() As Point
    Public Property CellColor() As Color
    Public Property SelectedCellColor() As Color
    Public Property GridColor() As Color
    Public Property GridSize() As Size
        Get
            Return Me.CurrentGridSize
        End Get
        Set(value As Size)
            Me.CurrentGridSize = value
            SetCellSize()
        End Set
    End Property
    Public Property GridColumnsRows() As Size
        Get
            Return Me.GridColRows
        End Get
        Set(value As Size)
            Me.GridColRows = value
            SetCellSize()
        End Set
    End Property
    Private Property RefreshCell() As GridCell

    Friend Class GridCell
        Public Property Cell() As Rectangle
        Public Property CellColor() As Color
    End Class

    Private Sub SetCellSize()
        Me.CellSize = New Size((Me.CurrentGridSize.Width \ Me.GridColRows.Width),
                               (Me.CurrentGridSize.Height \ Me.GridColRows.Height))
        If Me.CellSize.Width < 4 Then Me.CellSize.Width = 4
        If Me.CellSize.Height < 4 Then Me.CellSize.Height = 4
    End Sub

    Public Sub BuildGrid()
        If Me.Canvas Is Nothing Then Return 

        Me.Grid = New List(Of List(Of GridCell))()
        For row As Integer = 0 To GridColumnsRows.Height - 1
            Dim RowCells As New List(Of GridCell)()
            For col As Integer = 0 To GridColumnsRows.Width - 1
                RowCells.Add(New GridCell() With {
                    .Cell = New Rectangle(New Point(Me.GridPosition.X + (col * Me.CellSize.Width),
                                                    Me.GridPosition.Y + (row * Me.CellSize.Height)),
                                          Me.CellSize),
                    .CellColor = Me.CellColor})
            Next
            Me.Grid.Add(RowCells)
        Next
        Me.NewGrid = True
        Me.Canvas.Invalidate()
    End Sub

    Private Sub ControlPaint(o As Object, e As PaintEventArgs)
        If Me.NewGrid Then
            e.Graphics.Clear(Me.Canvas.BackColor)
            Me.NewGrid = False
        End If

        Me.Grid.
            SelectMany(Function(rowcells) rowcells).
            Select(Function(colcell)
                       If Me.UpdateCell Then
                           Using brush As New SolidBrush(Me.RefreshCell.CellColor)
                               e.Graphics.FillRectangle(brush, Me.RefreshCell.Cell.X + 1, Me.RefreshCell.Cell.Y + 1,
                                                               Me.RefreshCell.Cell.Width - 1, Me.RefreshCell.Cell.Height - 1)
                           End Using
                           Me.UpdateCell = False
                           Return Nothing
                       Else
                           Using pen As New Pen(Me.GridColor)
                               e.Graphics.DrawRectangle(pen, colcell.Cell)
                           End Using
                           Using brush As New SolidBrush(colcell.CellColor)
                               e.Graphics.FillRectangle(brush, colcell.Cell.X + 1, colcell.Cell.Y + 1,
                                                               colcell.Cell.Width - 1, colcell.Cell.Height - 1)
                           End Using
                       End If
                       Return colcell
                   End Function).TakeWhile(Function(colcell) colcell IsNot Nothing).ToList()
    End Sub

    Private Sub MouseHandler(o As Object, e As MouseEventArgs)
        Me.RefreshCell = GetUpdateCell(e.Location)
        Me.RefreshCell.CellColor = Me.SelectedCellColor
        Dim CellColorArea As Rectangle = Me.RefreshCell.Cell
        CellColorArea.Inflate(-1, -1)
        Me.UpdateCell = True
        Me.Canvas.Invalidate(CellColorArea)
    End Sub

    Private Function GetUpdateCell(CellPosition As Point) As GridCell
        Return Me.Grid.
            SelectMany(Function(rowcells) rowcells).
            Select(Function(gridcell) gridcell).
            Where(Function(gridcell) gridcell.Cell.Contains(CellPosition)).
            First()
    End Function

    Public Sub Dispose() Implements IDisposable.Dispose
        If Me.Canvas IsNot Nothing Then
            RemoveHandler Me.Canvas.Paint, AddressOf Me.ControlPaint
            RemoveHandler Me.Canvas.MouseClick, AddressOf Me.MouseHandler
            Me.Grid = Nothing
        End If
    End Sub
End Class

推荐阅读