使用C#创建可调整大小的网格以覆盖图像 [英] Creating a resizable grid to overlay on a image using c#

查看:141
本文介绍了使用C#创建可调整大小的网格以覆盖图像的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试找出一种方法,其中用户可以在图像上拖动网格,然后调整列和行的大小以适合图像.我将如何创建这样的东西?我无法在网上找到任何类似的东西.

I am trying to figure out a method in which the user can drag a grid over a image and then resize the columns and rows to fit the image. How would i go about creating something like this ? I have not been able to find anything similar online.

我想让用户在图像上拖动网格并调整其大小以适合图像.

I want to have the user drag a grid over the image and resize it to fit the image.

他们将下面的网格拖到图像上(即数字)

They drag the below grid over the image (being the numbers)

并在调整表大小后最终像这样结束

and end up like this, after resizing the table

因此,从本质上讲,我们具有一个形式的图像,然后是一个可拖动且可调整大小的网格以用于图像.

So essentially, we are having a image in the form and then a draggable and resizable grid to use over the image.

最后,我想让用户在图像上的数据上拖动网格,然后我想使用OCR读取与图像上的单元格相对应的每个区域中的数据. 这样,我就可以在第2行中选择说2列,并专门读取该数据.

In the end I want to have the user drag a grid over data in an image i then want to use OCR to read the data in each area corresponding to the cell on the image. That way I can then choose say col 2 in row 2 and read specifically just that data.

推荐答案

这里是一个网格类,可以叠加在任何Control上,并将绘制N x M线网格.

Here is a grid class that can be overlaid over any Control and will draw an N x M grid of lines.

您可以用鼠标移动线条,并用鼠标右键移动网格.您可以在两个List<int> XsYs中访问当前的x-和y-值.

You can move the lines with the mouse and move the grid with the right mouse button. You can access the current x- and y- values in the two List<int> Xs and Ys.

这是一个Panel子类,您应确保其具有正确的大小以及行和列的数量.

It is a Panel subclass and you should make sure it has the correct size and number of rows and columns.

让我们看看它的作用:

要设置它,请使用Init功能.

To set it up use the Init function..

这是代码:

public partial class Grid : Panel
{
    public Grid()
    {
        InitializeComponent();
        GridColor = Color.DarkMagenta;
        HandleSize = 4;
        BackColor = Color.Transparent;
        DoubleBuffered = true;
    }

    int RowCount { get; set; }
    int ColCount { get; set; }
    Color GridColor { get; set; }
    int HandleSize { get; set; }

    List<int> Xs { get; set; }
    List<int> Ys { get; set; }

    public void Init(int cols, int rows)
    {
        RowCount = rows;
        ColCount = cols;
        Xs = new List<int>();
        Ys = new  List<int>();
        float w = 1f * Width / cols;
        float h = 1f * Height / rows;

        for (int i = 0; i <= cols; i++) Xs.Add((int)(i * w));
        for (int i = 0; i <= rows; i++) Ys.Add((int)(i * h));
        // draw inside the panel only
        if (Xs[cols] == Width) Xs[cols]--;
        if (Ys[rows] == Height) Ys[cols]--;
    }

    public void Init(int cols, int rows, Size sz)
    {
        Size = sz;
        Init(cols, rows);
    }

    protected override void OnPaint(PaintEventArgs pe)
    {
        base.OnPaint(pe);

        using (Pen pen = new Pen(GridColor))
        {
            foreach (int x in Xs) pe.Graphics.DrawLine(pen, x, 0, x, Height);
            foreach (int y in Ys) pe.Graphics.DrawLine(pen, 0, y, Width, y);
        }
    }

    private Point mDown = Point.Empty;

    protected override void OnMouseDown(MouseEventArgs e)
    {
        base.OnMouseDown(e);
        if (Cursor != Cursors.Default) mDown = e.Location;
    }

    protected override void OnMouseMove(MouseEventArgs e)
    {
        base.OnMouseMove(e);

        // distances
        var dx = Xs.Select(x => Math.Abs(x - e.X));
        var dy = Ys.Select(y => Math.Abs(y - e.Y));
        // smallest distance
        int mx = dx.Min();
        int my = dy.Min();
        // grid index
        int ix = dx.ToList().IndexOf(mx);
        int iy = dy.ToList().IndexOf(my);

        if (e.Button.HasFlag(MouseButtons.Right))
        {   // move the grid with the right mouse button
            Location = new Point(Left + e.X - mDown.X, Top + e.Y - mDown.Y);
        }
        else if (!e.Button.HasFlag(MouseButtons.Left))
        {   // if we are close enough set cursor
            Cursor = Cursors.Default;
            if (mx < HandleSize) Cursor = Cursors.SizeWE;
            if (my < HandleSize) Cursor = Cursors.SizeNS;
            if (mx < HandleSize && my < HandleSize) Cursor = Cursors.SizeAll;
        }
        else
        {   // else move grid line(s)
            if (Cursor == Cursors.SizeWE  || Cursor == Cursors.SizeAll)
               Xs[ix] += e.X - mDown.X;
            if (Cursor == Cursors.SizeNS  || Cursor == Cursors.SizeAll) 
               Ys[iy] +=  e.Y - mDown.Y;
            Invalidate();
            mDown = e.Location;
            // restore order in case we overshot
            Xs = Xs.OrderBy(x => x).ToList();
            Ys = Ys.OrderBy(x => x).ToList();
        }
    }
}

这只是一个快速的镜头,因此很多事情可以而且应该加以改进,例如添加和删除列和行,验证等.

It was just a quick shot, so many things can and probably should be improved, like adding and removing columns and rows, validating etc..

我将其设置为覆盖这样的Panel panel1:

I set it up to overlay a Panel panel1 like this:

Grid grid1 = new Grid();
panel1.Controls.Add(grid1);
//grid1.Size = panel1.ClientSize;    // overlay full area..or..
grid1.Init(4, 3, new Size(99, 44));  // .. use the overload with size
grid1.Invalidate();

要让用户将其放置在所需的位置并调整其大小,可以改用常规的鼠标事件.

To let the user place and size it where he wants it you can use the usual mouse events instead..

更新:重新阅读时,我看到您也想让用户调整网格的大小.这是一个如何扩展代码以允许从左边缘或右边缘调整大小的示例.

Update: On re-reading I saw that you wanted to let the user resize the grid as well. Here is an example of how to expand the code to allow resizing from the left or right edge..:

        {   // else move gridline or size grid
            if (Cursor == Cursors.SizeWE  || Cursor == Cursors.SizeAll)
            {
                int delta = mDown.X - e.X;
                if (ix == 0)  // left edge: resize
                {
                    Width += delta;
                    Left -= delta;
                    Xs[Xs.Count - 1] = Width - 1;
                }
                else if (ix == Xs.Count - 1)  // right edge resize
                {
                    Width -= delta;
                    Xs[Xs.Count - 1] = Width - 1;
                }
                else Xs[ix] -= delta;  // move gridline
            }

顶部&底部边缘将以相同的方式工作.像过线一样,调整大小也可以从角落开始进行.

The top & bottom edges will work the in the very same way. Like with the line crossings resizing will also work from the corners..

更新:可以使用PictureboxLabel(对于Autosize=false );都具有开箱即用的DoubleBuffered属性,并且比Panels更好地支持绘图.

Update: Instead of a Panel, which is a Container control and not really meant to draw onto you can use a Picturebox or a Label (with Autosize=false); both have the DoubleBuffered property turned on out of the box and support drawing better than Panels do.

这篇关于使用C#创建可调整大小的网格以覆盖图像的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆