首页 > 解决方案 > 如何在winform上绘制矩阵

问题描述

我有一个空类 Box,我在下面制作了一个像你这样的矩阵,我想在 winform 上绘制这个矩阵我该怎么做?

例如,如果Box[i,j]有红色并且我像这样更改框的颜色,那么Box[i.j].color = Color.Black我的 winform 是否应该Box[i,j]在绘制整个矩阵后将颜色更改为黑色。

   Box[,] boxes = new Box[100, 100];
    MainForm form;
    Timer timer;

    public Game()
    {
        form = new MainForm();
        timer = new Timer();
    }

    public void Run(int size)
    {
        form.Paint += new PaintEventHandler(Draw);

        timer.Tick += new EventHandler(TimerEventHandler);
        timer.Interval = 1000 / 25;
        timer.Start();

        form.Visible = true;

    }

    private void TimerEventHandler(Object obj, EventArgs args)
    {
        form.Refresh();
    }

    private void Draw(Object obj, PaintEventArgs args)
    {

    }

标签: c#

解决方案


这是一种方法(不是唯一的方法):

首先,给出Box一个将自身绘制到 Graphics 上下文的方法:

class Box
{
    public Color color { get; set; } = Color.Red;
    // Note: Conventionally, property names begin with a capital letter.

    /// <summary>
    /// Draw this block to the given graphics context.
    /// </summary>
    /// <param name="g">The graphics context to draw to.</param>
    /// <param name="x">X-coordinate of the block within the graphics context.</param>
    /// <param name="y">Y-coordinate of the block within the graphics context.</param>
    /// <param name="width">Width of the area in which to draw the block.</param>
    /// <param name="height">Height of the area in which to draw the block.</param>
    public void DrawTo(Graphics g, int x, int y, int width, int height)
    {
        // Fill in the color of this block:
        Brush brush = new SolidBrush(color);     // fill style, color etc.
        g.FillRectangle(brush, x, y, width, height);

        // Black outline:
        Pen pen = new Pen(Color.Black);       // line style, color, etc.
        g.DrawRectangle(pen, x, y, width, height);

        // look up the documentation of the System.Drawing.Graphics class for other methods for drawing.
    }
}

现在,如果您想将矩阵绘制为位图图像,您可以这样做:

    private void DrawMatrix(System.Drawing.Bitmap bm)
    {
        Graphics g = Graphics.FromImage(bm);
        try
        {
            for (int y = 0; y < MatrixHeight; y++)
                for (int x = 0; x < MatrixWidth; x++)
                {
                    boxes[x, y].DrawTo(g, x * CellWidth, y * CellHeight, CellWidth, CellHeight);
                }
        }
        finally
        {
            g.Dispose();
        }
    }

    // Size of the matrix:
    const int MatrixWidth = 100;
    const int MatrixHeight = 100;

    // Size of each cell in pixels:
    const int CellWidth = 20;
    const int CellHeight = 20;

但这对于每帧都太慢了(对于 100x100 矩阵)。如果您在更改单个单元格时只更新它们,则可以像这样更新屏幕外图像。

然后,您可以PictureBox在窗体上放置一个控件,并将其Image属性设置为此处更新的位图。您可以使用创建该位图(此方法的参数)new Bitmap(MatrixWidth * CellWidth, MatrixHeight * CellHeight)

或者,您可以在 OnPaint 事件处理程序(Draw您问题中的方法)中绘制表单的画布。假设窗口滚动(并且并非所有矩阵在任何时候都在视口中可见),您将仅循环通过可见单元格并使它们自己绘制到表单的 Graphics 上下文中。

表单的 Graphics 上下文是Graphics事件参数对象的属性。这就是上述Box.Draw方法所需要的。绘制每个单元格时,您必须考虑其在网格中的位置以及窗口的滚动方式,以便计算要传递给该方法的坐标。

每次调用 OnPaint 事件时,只需重绘窗口的一部分。这部分由属性给出ClipRectangle。(Windows 将要重绘的区域分解为一个或多个矩形,并对每个矩形进行调用。)(ClipRectangle可能是整个窗口。)允许在此范围之外进行绘制,但可能效率低下。

因此,为了提高效率,您应该只遍历至少部分落在 内的所有单元格ClipRectangle,计算它们在可见区域内的位置并调用它们的Box.Draw.

该类使用的坐标Graphics是可见坐标,因此 (0,0) 是窗口的左上角,与滚动无关。

查看滚动位置的这些属性:

Form.HorizontalScroll.Value
Form.VerticalScroll.Value

推荐阅读