如何使用 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# 管理对一组面板的点击事件?的主要内容,如果未能解决你的问题,请参考以下文章