2

我正在开发一个非常基本的绘图程序:一个由多个 RectangleShapes 组成的 2D 网格,每个大约 20x30 像素,单击时会根据用户 RGB 输入更改颜色,效果很好:

Color SelectedColor = new Color();
private void Pixel_1_1_Click(object sender, EventArgs e)    // on Rectangle click
{
    Pixel_1_1.FillColor = SelectedColor;    // change to currently desired color.
}

由于正方形的数量急剧增加,我正在寻找一种将“像素”矩形排列成二维数组的方法。(我真的不想为屏幕上的每个 Rectangle 创建一个 Pixel_Click 方法!)希望最终能够调用类似:

private void Pixel_[x]_[y]_Click(object sender, EventArgs e)
{
    Pixel_[x]_[y].FillColor = SelectedColor;
}

我的朋友建议使用匿名代表,但我不明白如何充分使用匿名代表来解决我的问题。

在 C# Windows 窗体中生成二维矩形数组的最佳方法是什么?一旦生成,我如何使用单一方法访问它们以获取 x 和 y 的变体值?

4

3 回答 3

1

如果要将矩形作为组件保留在屏幕上,则可以将所有矩形分配给相同的单击事件,单击事件将有一个小下拉菜单来选择现有事件。要知道单击了哪个矩形,请使用sender参数((Pixel)sender).FillColor = SelectedColor;

为方便起见,我建议使用面板之类的东西并在其上绘制矩形,这意味着您只需处理一个单击事件。所以现在你的问题变成了“如何在面板上绘制矩形网格”和“我怎么知道点击了哪个矩形”

因此,对于第一部分,您可以使用这不是非常有效的方法。

创建一个存储有关像素信息的类

class MyPixel
{
    public Color PixelColour;
    public Rectangle Bounds;
}

将它们的列表保存在内存中

List<MyPixels> MyGrid = new List<MyPixels>();

然后在面板的onpaint事件中绘制面板上的像素

foreach(MyPixel Pixel in MyGrid)
{
    using(Brush B = new SolidBrush(Pixel.PixelColor))
    {
        e.Graphics.DrawRectangle(B, Pixel.Bounds);
    }
}

现在在点击事件中,您需要知道点击了哪个像素

foreach(MyPixel Pixel in MyGrid)
{
    if (Pixel.Bounds.Contains(e.Location))
    {
        PixelClicked(Pixel);
    }
}
于 2012-07-03T15:26:08.987 回答
1

虽然您将每个矩形视为一个对象可能是正确的,但将每个矩形视为一个窗口控件可能是不正确的,特别是因为您有这么多窗口控件。

所以尝试创建自己的矩形对象:

public class MyRect {
  public Color FillColor { get; set; }
  public Rectangle Rectangle { get; set; }

  public MyRect(Rectangle r, Color c) {
    this.Rectangle = r;
    this.FillColor = c;
  }
}

现在您只需要保留一个对象列表并在一个 Panel 控件(或 PictureBox)上绘制所有矩形:

private List<MyRect> myRectangles = new List<MyRect>();

public Form1() {
  InitializeComponent();

  myRectangles.Add(new MyRect(new Rectangle(10, 10, 64, 16), Color.Blue));
  myRectangles.Add(new MyRect(new Rectangle(20, 48, 16, 64), Color.Red));
}

private void panel1_Paint(object sender, PaintEventArgs e) {
  foreach (MyRect mr in myRectangles) {
    using (SolidBrush sb = new SolidBrush(mr.FillColor)) {
      e.Graphics.FillRectangle(sb, mr.Rectangle);
    }
  }
}

要处理矩形的“单击”事件,您只需处理容器控件的MouseDownorMouseClick事件并确定自己单击的是哪个矩形:

void panel1_MouseDown(object sender, MouseEventArgs e) {
  if (e.Button == MouseButtons.Left) {
    foreach (MyRect mr in myRectangles) {
      if (mr.Rectangle.Contains(e.Location)) {
        ChangeColor(mr, Color.Green);
      }
    }
    panel1.Invalidate();
  }
}

private void ChangeColor(MyRect mr, Color newColor) {
  mr.FillColor = newColor;
}
于 2012-07-03T15:26:38.270 回答
0

我相信你会以错误的方式解决这个问题。您要做的是直接绘制到位图中。这是一些使用 PictureBox 允许用户在其中绘制的代码。

    using System;
    using System.Drawing;
    using System.Windows.Forms;

    namespace WindowsFormsApplication1
    {
        public partial class Form1 : Form
        {
            private Pen _pen;

            private bool _mouseDown;
            private int _startX;
            private int _startY;

            public Form1()
            {
                InitializeComponent();
            }

            private void Form1_Load(object sender, EventArgs e)
            {
                pictureBox1.Image = new Bitmap(pictureBox1.Width, pictureBox1.Height);
                _pen = new Pen(Color.Black);
            }

            private void pictureBox1_MouseDown(object sender, MouseEventArgs e)
            {
                _mouseDown = true;

                _startX = e.X;
                _startY = e.Y;
            }

            private void pictureBox1_MouseUp(object sender, MouseEventArgs e)
            {
                _mouseDown = false;
            }

            private void pictureBox1_MouseMove(object sender, MouseEventArgs e)
            {
                if (_mouseDown)
                {
                    using (var graphics = Graphics.FromImage(pictureBox1.Image))
                    {
                        graphics.DrawLine(_pen, _startX, _startY, e.X, e.Y);
                        _startX = e.X;
                        _startY = e.Y;
                    }
                    pictureBox1.Invalidate();
                }
            }

        }
    }

这是编写绘画应用程序的常规方法,并且性能也非常好。您还可以通过这种方式轻松保存、编写新工具或更好地操作图像。

于 2012-07-03T15:30:37.163 回答