vb.net - 我可以画的网格
问题描述
所以我正在尝试创建一个应用程序来简化像素艺术(学校项目)的创建,到目前为止我所做的是在面板中绘制一个网格,下一步是允许用户单击一个单元格并拥有它画了,但我无法让它工作,这是我的代码:
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
这会绘制一个包含用户想要的列数和行数的网格,但我一直在努力允许绘画
我一直在想的是:处理此代码,并创建一个“像素”类,根据用户行和列创建“像素”对象的数量,并单独绘制每个对象,然后只需更改每个“像素”的颜色
解决方案
这是一个Grid
允许设置其单元格颜色的类。
使用.Grid
引用单元格List(Of List(Of Class))
。
Cell
Object 类包含一个简单的属性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表面上检测到鼠标单击时,该属性会报告单击发生的坐标。Grid
Paint()
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 中创建 aPanel
和Button
a 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
推荐阅读
- java - 如何将“对象”转换为未知的自定义数据类型/类对象?
- java - 如何在 Android 中的多个活动和片段中保留对象?
- node.js - mongodb 连接大约需要 10 秒
- python - 据称正确的 SPARQL 查询(Wikidata)在 Python 中没有产生任何结果
- python - 有没有办法使用熊猫将多个标志列汇总为一个?
- python-3.x - 如何从python数组创建对象
- python - 使用 numpy 数组 Pandas 修改数据框中多列的快速方法
- r - 如何在 RStudio 中创建未堆叠的点图?
- arrays - 为什么 Object.Keys.().length 显示非空值,即使它在 mongoDB 中有 0 个项目?
- reactjs - React Native TypeSrcript 函数返回 JSX.Element 类型