在C#中绘制形状不起作用

时间:2015-01-20 03:13:13

标签: c# forms

我有一个C#程序,我正在尝试绘制GUI。此程序是一个2D数组,其中数组中的每个点可以具有不同类型的Space对象:AsteroidEmptySpaceGravityWell

我的SpaceProbeView类将传递2D数组,然后在表单的每个空间中绘制一个小矩形,具有不同的颜色,具体取决于Space对象。

我遇到的问题是我的程序实际上没有绘制任何东西。我可以添加一个随机矩形并从Graphics对象中绘制它,但这就是所有绘制的。难道我做错了什么?我是Windows Forms的新手。

以下是SpaceProbeView类:

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子类的代码EmptySpace(添加所有子类似乎没必要,它们都遵循这种模式):

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类:

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);
        }
    }
}

1 个答案:

答案 0 :(得分:1)

这实际上是完整的代码示例吗?如果是这样,那么您的问题是您永远不会初始化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实例(我知道,您也不会),所有实例都将共享相同的画笔。< / p>

其他Space子类也是如此,包括根据需要制作brush字段readonlystatic

我还要注意,持有像Brush这样的可支配资源的类应该实现IDisposable。当然,你应该在完成这些课程后处理这些课程的实例。

SpaceProbeView课程中:

    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);
    }

我以为我理解了mapSizerowSize的初始化,但后来我看到了Size的初始化。 5来自哪里?为什么表单的大小是5x与空格总数一样大,而不仅仅是两个维度(行或列)中的空格数?

根据用法,我会将map对象传递给构造函数。虽然调用者传递numberOfSpaces的有效值,但您在此处使用的代码仍可正常工作,但您实际上无法确保它与稍后设置的map对象的实际尺寸相匹配。 / p>

如果您传递map对象本身,则可以从该对象中简单地检索行和列维度,甚至不需要调用者传递方形图。在这种情况下,你可能完全摆脱mapSize变量;目前还不清楚你为什么要这样做。