如何使用 C# 管理对一组面板的点击事件?

Posted

技术标签:

【中文标题】如何使用 C# 管理对一组面板的点击事件?【英文标题】:How to manage click events made to an array of panels with C#? 【发布时间】:2021-12-24 21:42:28 【问题描述】:

我正在开发一个在线跳棋程序,并且成功地在每个方格上绘制了棋盘和跳棋。现在唯一的问题是对点击事件进行编程,我有代码可以响应对单个面板的点击,以将背景颜色更改为蓝色,将检查器颜色更改为白色,当用户单击同一块面板时,颜色为变回原来的样子。现在我的问题是实现这种效果:: 如果用户单击 panelA 然后应用颜色冲突,当单击不同的 panelB 时,应用于 panelA 的颜色应该恢复到原来的颜色,就像双击一样效果

我尝试的解决方案

我初始化了一个List<Panel> clicked_objects 对象并用它来存储被点击的Panel 元素,我希望列表对象的计数随着每次连续点击而增加,但是当我执行MessageBox.Show(clicked_objects.Count.ToString()) 时,它总是显示1. 我需要这样做,以便立即将第二次单击的Panel 添加到此列表中,我可以在index 1(new Panel) 检查面板的计数和颜色,并在index 0(previously clicked Panel) 对面板进行脱色。我怎样才能做到这一点?单击一个面板会删除先前单击的元素上的颜色(如果有)?

代码

public class Checkerpiece
     
        //declare a panel array for storing clicked Panels
        List<Panel> clicked_squares=new List<Panel>();
        //The object above can only hold two panel elements
        //colors of the rounded pieces
        Color color;
        //specify where the checker is drawn
        Panel target_square;
        //specify the center of the circle
        float center_x;
        float center_y;
        //specify the radius of the checker piece
        float radii;
        //define some foreground color that will be used to access the color of the checker
        Color foreground;
        //fill the details inside the constructor
        public Checkerpiece(Panel mypanel,Color color)
        
            this.color = color;
            this.target_square = mypanel;
            this.center_x = mypanel.Width / 2;
            this.center_y = mypanel.Height / 2;
            this.radii = mypanel.Width / 2;
            //register an onclick listener for our checkerpiece object
            this.target_square.Click += Target_square_Click;
           // this.target_square.MouseClick += Target_square_MouseClick;
        

      
        private void Target_square_Click(object sender, EventArgs e)
        
            clicked_squares.Add(target_square);
           //this keeps showing 1 no mater what panel I click
            MessageBox.Show(clicked_squares.Count.ToString());
         
          public static void fillCircle(Graphics g, Brush b, float centerX, float centerY, float radius)
        
            g.FillEllipse(b, centerX - radius, centerY - radius,
                     radius + radius, radius + radius);
        
        //implement a getter for the color used to used to draw the checker
        public Color getCheckerColor()
        
            return this.color;
        
  

棋盘类

public partial class Form1 : Form
    
        private Panel[,] _chessBoardPanels;
        public Form1()
        
            InitializeComponent();
            
        
      
       
        private void Form1_Load(object sender, EventArgs e)
        
            const int tileSize = 100;
            const int gridSize = 8;
            var clr1 = Color.DarkGray;
            var clr2 = Color.White;

            // initialize the "chess board"
            _chessBoardPanels = new Panel[gridSize, gridSize];
            int count = 0;
            // double for loop to handle all rows and columns
            for (var n = 0; n < gridSize; n++)
            
                for (var m = 0; m < gridSize; m++)
                
                    // create new Panel control which will be one 
                    // chess board tile
                    var newPanel = new Panel
                    
                        Size = new Size(tileSize, tileSize),
                        Location = new Point(tileSize * n, tileSize * m)
                      
                ;
                    //register an event listener for each square

                   
                    // add to Form's Controls so that they show up
                    Controls.Add(newPanel);

                    // add to our 2d array of panels for future use
                    _chessBoardPanels[n, m] = newPanel;
                    //draw only the red checkers on top of the board
                    
                    // color the backgrounds
                    if (n % 2 ==0)
                        newPanel.BackColor = m % 2 != 0 ? clr1 : clr2;
                        //new Checkerpiece(newPanel, Color.Red).draw();
                    
                    else
                        newPanel.BackColor = m % 2 != 0 ? clr2 : clr1;
                    //draw a new checker piece
                    if (newPanel.BackColor==Color.White &&m<=3)
                        new Checkerpiece(newPanel, Color.Red).draw(); 
                       ;
                    if (newPanel.BackColor == Color.White && m > 4)
                        new Checkerpiece(newPanel, Color.Black).draw();
               
                
            
           
        

输出

当我点击一块时,每种颜色都会保留在先前点击的项目上,这不应该是这种情况

目标

如何存储被点击面板的状态并在点击新面板时恢复?

【问题讨论】:

这个 checkerPiece 类是正方形吗?有道理为什么它只有 1 不是吗?它是一个正方形。 好像你需要一个董事会课程?那是哪里? @TMcKeown,用董事会代码更新我的代码 点击的方块不属于棋盘吗? 但你的问题是为什么这块(一个正方形)只有一块。如果单击正方形,则将其添加到列表中,因此每个正方形列表仅在您单击该实例时才会包含条目。我想我不明白你想要什么,我认为 board 类会有被点击的片段列表,你的代码有片段跟踪有人点击了多少次,对吧? 【参考方案1】:

您应该管理 Board 类中的片段,可以通过引用检查片段列表,当您通过单击事件获得对象时,无需在集合中“查找”匹配的片段。使用 Board (Form) 类来管理当前选择的部分,并在设置这些属性时处理选择/取消选择。

【讨论】:

@T McKeown,比较有一个错误,发布循环并查看我在哪里做错了,它成功地为活动点击的元素着色并从先前点击的 \item 中移除着色但随后使董事会的其余部分变白大声笑 我需要查看更多代码。 @T McKeown,我编辑了包含输出图片的问题。更新代码,以便您可以看到我如何从 Form1 访问元素并检查它是否可以着色但它是错误的 看起来您正在遍历列表并更改颜色?您应该只需要 Select() 当前片段和 Deselect() 上一个片段。您应该在 Piece 类中添加 Select() 和 Deselect() 方法,电路板应该在实例上调用适当的方法。当您所做的只是选择/取消选择(2 件)时,无需遍历所有件 @T McKeown,同意。循环遍历所有面板会使代码变慢,线性时间复杂度。你能分享一些我可以在 Checkerpiece 类中实现的代码来选择和取消选择一块吗?

以上是关于如何使用 C# 管理对一组面板的点击事件?的主要内容,如果未能解决你的问题,请参考以下文章

我如何在 webBrowser 中使用 c# 执行点击事件

如何使用c#从其他形式的菜单项中显示月历上的当前日期

C#按钮事件问题

unity如何在事件被触发后在屏幕上显示text

Unity|点击事件属性详情|小技巧

Unity|点击事件属性详情|小技巧