在 C# 中绘制形状不起作用
Drawing Shapes in C# Not Working
我有一个 C# 程序,我正在尝试为其绘制 GUI。该程序是一个二维数组,其中数组中的每个点都可以有不同类型的 Space
对象:Asteroid
、EmptySpace
或 GravityWell
.
我的 SpaceProbeView
class 将传递二维数组,然后在每个 space 中绘制一个小矩形,根据 Space
不同的颜色对象。
我 运行 遇到了我的程序实际上没有绘制任何东西的问题。我可以添加一个随机矩形并从 Graphics 对象中绘制它,但仅此而已。难道我做错了什么?我对 Windows 表单完全陌生。
这里是 SpaceProbeView
class:
using System;
using System.Windows.Forms;
using System.Drawing;
using System.Collections;
namespace SpaceProbe
{
class SpaceProbeView : Form
{
private int squareSize;
public int SquareSize
{
get { return squareSize; }
set { squareSize = value; }
}
private Space[,] map;
public void setMap(Space[,] aMap) { map = aMap; }
private int mapSize;
private int rowSize;
public SpaceProbeView(int numberOfSpaces)
{
mapSize = numberOfSpaces;
rowSize = (int)Math.Sqrt(mapSize);
Size = new System.Drawing.Size(mapSize *5, mapSize * 5);
}
protected override void OnPaint(PaintEventArgs e)
{
Graphics graphics = e.Graphics;
for(int row = 0; row < rowSize; row++)
{
for(int column = 0; column < rowSize; column++)
{
graphics.FillRectangle(map[row, column].getBrush(), row * SquareSize,
column * SquareSize, SquareSize, SquareSize);
}
}
}
}
}
我的Space
界面是:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Drawing;
namespace SpaceProbe
{
public interface Space
{
SolidBrush getBrush();
}
}
与 Space
subclasses 之一的代码,EmptySpace
(添加所有 subclasses 似乎没有必要,它们都遵循这种模式) :
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Drawing;
namespace SpaceProbe
{
class EmptySpace : Space
{
private static EmptySpace instance = new EmptySpace();
public static EmptySpace Instance
{
get { return instance; }
set { }
}
private SolidBrush brush = new SolidBrush(Color.DeepPink);
public SolidBrush getBrush() { return brush; }
private EmptySpace() { }
}
}
和 Map
class:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Collections;
namespace SpaceProbe
{
class Map
{
private Space[,] map;
public Space[,] TheMap
{
get { return map; }
set { }
}
public Map(int size)
{
map = new Space[size, size];
Random random = new Random();
for (int row = 0; row < size; row++)
{
for (int column = 0; column < size; column++)
{
//TODO: make this so that it enforces the right quantity of each, not just a vague percentage
int randomInt = random.Next(11);
if (randomInt <= 1)
map[row, column] = GravityWell.Instance;
else if (randomInt > 1 && randomInt <= 7)
map[row, column] = EmptySpace.Instance;
else if (randomInt > 7 && randomInt <= 10)
map[row, column] = Asteroid.Instance;
}
}
}
}
}
全部 运行 在:
using System;
using System.Windows.Forms;
namespace SpaceProbe
{
class Program
{
static void Main(string[] args)
{
Map map = new Map(10);
SpaceProbeView view = new SpaceProbeView(100);
view.setMap(map.TheMap);
Application.Run(view);
}
}
}
这实际上是完整代码示例吗?如果是这样,那么您的问题是您从未初始化 SquareSize
属性。由于它是 0
,您的矩形是空的,因此当您调用 FillRectangle()
.
时当然不会绘制任何内容
只要我在这里:),我也会推荐一些其他的改变。例如,以下是更惯用的 C#(不像 Java),并且还包括更好的实现实践:
class EmptySpace : Space
{
private static readonly EmptySpace instance = new EmptySpace();
public static EmptySpace Instance
{
get { return instance; }
}
private static readonly SolidBrush brush = new SolidBrush(Color.DeepPink);
public SolidBrush Brush { get { return brush; } }
private EmptySpace() { }
}
换句话说,当你有类似 属性 的语义时,你应该使用真实的属性。此外,如果不应更改某个字段,请使用 readonly
声明(类似于 Java 中的 final
,至少在此上下文中)。最后,您不妨将 brush
字段设置为静态,因为即使您有多个 EmptySpace
实例(我知道,您不会),所有实例都会共享同一个画笔。
其他 Space
子 class 也是如此,包括根据需要制作 brush
字段 readonly
和 static
。
我还会注意到 class 持有像 Brush
这样的一次性资源的 es 应该实现 IDisposable
。当然,当你用完这些 classes 时,你应该释放它们。
在你的 SpaceProbeView
class:
private Space[,] map;
public void setMap(Space[,] aMap) { map = aMap; }
同样,更好的是:
private Space[,] map;
public Space[,] Map
{
get { return map; } // avoid write-only properties
set { map = value; }
}
因为它同时用于行和列,所以:
private int mapSize;
private int rowSize;
应该是:
private int mapSize;
private int rowAndColumnSize;
(或类似的东西......只要明确它用于两者)
这段代码,我不是很懂:
public SpaceProbeView(int numberOfSpaces)
{
mapSize = numberOfSpaces;
rowSize = (int)Math.Sqrt(mapSize);
Size = new System.Drawing.Size(mapSize *5, mapSize * 5);
}
我以为我看懂了mapSize
和rowSize
的初始化,后来看到了Size
的初始化。 5
是从哪里来的?为什么您的表单大小是空格总数的 5 倍,而不仅仅是任一维度(行或列)中的空格数?
考虑到用法,我会直接将 map
对象传递给构造函数。只要调用者为 numberOfSpaces
传递有效值,您在此处的代码就可以工作,但您实际上没有任何方法可以确保它与稍后设置的 map
对象的实际尺寸相匹配。
如果您传递 map
对象本身,则可以简单地从该对象中检索行和列维度,您甚至不必要求调用者传递方形地图。在那种情况下,您可能会完全摆脱 mapSize
变量;根本不清楚你为什么要拥有它。
我有一个 C# 程序,我正在尝试为其绘制 GUI。该程序是一个二维数组,其中数组中的每个点都可以有不同类型的 Space
对象:Asteroid
、EmptySpace
或 GravityWell
.
我的 SpaceProbeView
class 将传递二维数组,然后在每个 space 中绘制一个小矩形,根据 Space
不同的颜色对象。
我 运行 遇到了我的程序实际上没有绘制任何东西的问题。我可以添加一个随机矩形并从 Graphics 对象中绘制它,但仅此而已。难道我做错了什么?我对 Windows 表单完全陌生。
这里是 SpaceProbeView
class:
using System;
using System.Windows.Forms;
using System.Drawing;
using System.Collections;
namespace SpaceProbe
{
class SpaceProbeView : Form
{
private int squareSize;
public int SquareSize
{
get { return squareSize; }
set { squareSize = value; }
}
private Space[,] map;
public void setMap(Space[,] aMap) { map = aMap; }
private int mapSize;
private int rowSize;
public SpaceProbeView(int numberOfSpaces)
{
mapSize = numberOfSpaces;
rowSize = (int)Math.Sqrt(mapSize);
Size = new System.Drawing.Size(mapSize *5, mapSize * 5);
}
protected override void OnPaint(PaintEventArgs e)
{
Graphics graphics = e.Graphics;
for(int row = 0; row < rowSize; row++)
{
for(int column = 0; column < rowSize; column++)
{
graphics.FillRectangle(map[row, column].getBrush(), row * SquareSize,
column * SquareSize, SquareSize, SquareSize);
}
}
}
}
}
我的Space
界面是:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Drawing;
namespace SpaceProbe
{
public interface Space
{
SolidBrush getBrush();
}
}
与 Space
subclasses 之一的代码,EmptySpace
(添加所有 subclasses 似乎没有必要,它们都遵循这种模式) :
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Drawing;
namespace SpaceProbe
{
class EmptySpace : Space
{
private static EmptySpace instance = new EmptySpace();
public static EmptySpace Instance
{
get { return instance; }
set { }
}
private SolidBrush brush = new SolidBrush(Color.DeepPink);
public SolidBrush getBrush() { return brush; }
private EmptySpace() { }
}
}
和 Map
class:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Collections;
namespace SpaceProbe
{
class Map
{
private Space[,] map;
public Space[,] TheMap
{
get { return map; }
set { }
}
public Map(int size)
{
map = new Space[size, size];
Random random = new Random();
for (int row = 0; row < size; row++)
{
for (int column = 0; column < size; column++)
{
//TODO: make this so that it enforces the right quantity of each, not just a vague percentage
int randomInt = random.Next(11);
if (randomInt <= 1)
map[row, column] = GravityWell.Instance;
else if (randomInt > 1 && randomInt <= 7)
map[row, column] = EmptySpace.Instance;
else if (randomInt > 7 && randomInt <= 10)
map[row, column] = Asteroid.Instance;
}
}
}
}
}
全部 运行 在:
using System;
using System.Windows.Forms;
namespace SpaceProbe
{
class Program
{
static void Main(string[] args)
{
Map map = new Map(10);
SpaceProbeView view = new SpaceProbeView(100);
view.setMap(map.TheMap);
Application.Run(view);
}
}
}
这实际上是完整代码示例吗?如果是这样,那么您的问题是您从未初始化 SquareSize
属性。由于它是 0
,您的矩形是空的,因此当您调用 FillRectangle()
.
只要我在这里:),我也会推荐一些其他的改变。例如,以下是更惯用的 C#(不像 Java),并且还包括更好的实现实践:
class EmptySpace : Space
{
private static readonly EmptySpace instance = new EmptySpace();
public static EmptySpace Instance
{
get { return instance; }
}
private static readonly SolidBrush brush = new SolidBrush(Color.DeepPink);
public SolidBrush Brush { get { return brush; } }
private EmptySpace() { }
}
换句话说,当你有类似 属性 的语义时,你应该使用真实的属性。此外,如果不应更改某个字段,请使用 readonly
声明(类似于 Java 中的 final
,至少在此上下文中)。最后,您不妨将 brush
字段设置为静态,因为即使您有多个 EmptySpace
实例(我知道,您不会),所有实例都会共享同一个画笔。
其他 Space
子 class 也是如此,包括根据需要制作 brush
字段 readonly
和 static
。
我还会注意到 class 持有像 Brush
这样的一次性资源的 es 应该实现 IDisposable
。当然,当你用完这些 classes 时,你应该释放它们。
在你的 SpaceProbeView
class:
private Space[,] map;
public void setMap(Space[,] aMap) { map = aMap; }
同样,更好的是:
private Space[,] map;
public Space[,] Map
{
get { return map; } // avoid write-only properties
set { map = value; }
}
因为它同时用于行和列,所以:
private int mapSize;
private int rowSize;
应该是:
private int mapSize;
private int rowAndColumnSize;
(或类似的东西......只要明确它用于两者)
这段代码,我不是很懂:
public SpaceProbeView(int numberOfSpaces)
{
mapSize = numberOfSpaces;
rowSize = (int)Math.Sqrt(mapSize);
Size = new System.Drawing.Size(mapSize *5, mapSize * 5);
}
我以为我看懂了mapSize
和rowSize
的初始化,后来看到了Size
的初始化。 5
是从哪里来的?为什么您的表单大小是空格总数的 5 倍,而不仅仅是任一维度(行或列)中的空格数?
考虑到用法,我会直接将 map
对象传递给构造函数。只要调用者为 numberOfSpaces
传递有效值,您在此处的代码就可以工作,但您实际上没有任何方法可以确保它与稍后设置的 map
对象的实际尺寸相匹配。
如果您传递 map
对象本身,则可以简单地从该对象中检索行和列维度,您甚至不必要求调用者传递方形地图。在那种情况下,您可能会完全摆脱 mapSize
变量;根本不清楚你为什么要拥有它。