c# - 在图片框内动态创建点/正方形

标签 c# .net winforms

我希望能够在图片框内创建 X x Y 数量的框/圆圈/按钮。完全像 Windows 碎片整理工具。

我尝试创建一个布局并不断向其添加按钮或图片框,但速度非常慢,在添加 200 个左右的图片框后它崩溃,窗口句柄或内存不足。

还有什么选择?你能告诉我一段简单的代码来添加盒子,就像碎片整理工具一样,我可以很容易地访问它们 box[x,y].Color = Green 当我的应用程序取得进展时?

目前我有这个:

        private void ResetTableStyles()
        {
            boardPanel.Controls.Clear();
            boardPanel.RowStyles.Clear();
            boardPanel.ColumnStyles.Clear();

            boardPanel.RowCount = Rows;
            boardPanel.ColumnCount = Columns;

            for (int i = 0; i < Rows; i++)
            {
                boardPanel.RowStyles.Add(new RowStyle(SizeType.Percent, 100f));
            }
            for (int j = 0; j < Columns; j++)
            {
                boardPanel.ColumnStyles.Add(new ColumnStyle(SizeType.Percent, 100f));
            }
        }

        private void CreateButtons()
        {
            for (int i = 0; i < Rows; i++)
            {
                for (int j = 0; j < Columns; j++)
                {
                    var button = new PictureBox
                    {
                        BackColor = Color.White,
                        Dock = DockStyle.Fill,
                        Margin = Padding.Empty,
                        Tag = new Point(i, j),
                        BackgroundImageLayout = ImageLayout.Stretch
                    };
                    //button.MouseDown += button_MouseDown;
                    boardPanel.Controls.Add(button, j, i);
                }
            }
        }

正如我所说,这不起作用,一段时间后它就会崩溃并且需要很长时间。

最佳答案

也许有人有更好的答案,但您可以使用 Panel 作为 Canvas 并处理 Paint 事件以将彩色矩形绘制到 Panel。然后,您可以使用鼠标事件(例如 MouseMove)来确定您所在的单元格。

这是一个 super 简单的概念证明。

// Data.cs
namespace WindowsFormsApplication
{
   public class Data
   {
      public int State { get; set; }
      public string Tip { get; set; }
   }
}

// Form1.cs
using System;
using System.Drawing;
using System.Windows.Forms;

namespace WindowsFormsApplication
{
   public partial class Form1 : Form
   {
      public Form1()
      {
         InitializeComponent();

         var rng = new Random();
         _data = new Data[30 * 30];
         for (int i = 0; i < _data.Length; i++)
         {
            _data[i] = new Data
            {
               State = rng.Next(0, 3),
               Tip = $"Data at index: {i}"
            };
         }
      }

      private Data[] _data;

      private void panel1_Paint(object sender, PaintEventArgs e)
      {
         using (var brush = new SolidBrush(Color.Gray))
         using (var buffer = BufferedGraphicsManager.Current.Allocate(e.Graphics,
            new Rectangle(0, 0, 450, 450)))
         {
            for (int x = 0; x < 30; x++)
            {
               for (int y = 0; y < 30; y++)
               {
                  int dataIdx = (y * 30) + x;
                  Data data = _data[dataIdx];
                  if (data.State == 1)
                  {
                     brush.Color = Color.Blue;
                  }
                  else if (data.State == 2)
                  {
                     brush.Color = Color.Red;
                  }
                  else
                  {
                     brush.Color = Color.Gray;
                  }
                  buffer.Graphics.FillRectangle(brush, x * 15, y * 15, 15, 15);
                  buffer.Graphics.DrawLine(Pens.Black, 0, y * 15, 450, y * 15); //Gridline
               }
               buffer.Graphics.DrawLine(Pens.Black, x * 15, 0, x * 15, 450); //Gridline
            }
            buffer.Render(e.Graphics);
         }
      }

      private void panel1_MouseMove(object sender, MouseEventArgs e)
      {
         var point = e.Location;
         int x = point.X / 15;
         int y = point.Y / 15;
         int dataIdx = (y * 30) + x;
         System.Diagnostics.Debug.WriteLine(_data[dataIdx].Tip);
      }
   }
}

Data 类表示面板上每个部分背后的模型,非常简单。

Form1 上放置了一个控件:名为 panel1Panel,大小为 450 x 450。面板上的每个单元格都是 15 x 15,因此我们有 30 列和 30 行。在 Form1 的构造函数中,我们初始化将用于绘制面板的 Data

Form1.panel1_Paint 内部,我们遍历单元格并查找给定单元格的 Data 实例。然后,根据 State,为单元格设置颜色并绘制该颜色的矩形。这是在缓冲区上完成的,因此面板在绘画时不会闪烁。

Form1.panel1_MouseMove 中,我们使用鼠标指针相对于 panel1 的位置来确定鼠标悬停在哪个单元格上,获取 的实例该单元格的数据,并在调试窗口中显示提示

您也许可以采用它并在此基础上进行构建,也许可以使用自定义 UserControl,这样您就可以轻松地访问具有列和行的每个单独的单元格...您的 box[x , y].Color = Colors.Green 上面的例子。

关于c# - 在图片框内动态创建点/正方形,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57910861/

相关文章:

c# - 如何使用MVC在div中显示图像

c# - 运行我的项目几次后,出现错误 : Could not resolve COM reference "f8937e53-d444-4e71-9275-35b64210cc3b" what's that?

c# - 双 ToString - 无科学记数法

c# - 如何使用 RsaProtectedConfigurationProvider 加密/解密配置文件部分

c# - 左右对齐 richtextbox c#

c# - 如何在另一个项目中调用一个项目中的类?

.net - 为什么 Task.WhenAll 抛出 TaskCanceledException 和 Task.WhenAny 不在同一个测试用例中

c# - 使用 sql server 作业代理运行 .exe 时访问被拒绝

c# - 当 DataSource 是 BindingList 时过滤 BindingSource

c# - 如何在 TreeView 中展开新添加的节点