C# 对象(类单元格)上的自定义单击事件仅在每次单击时为最后一个单元格触发
大家好,这是我的第一个问题。 我在使自定义创建的单元格类上的单击事件正常工作时遇到一些问题。到目前为止,它会在单击单元格时发出通知,但它只显示最后一个单元格被单击,即使您单击了第一个单元格。这是我的密码C# 对象(类单元格)上的自定义单击事件仅在每次单击时为最后一个单元格触发,c#,winforms,events,C#,Winforms,Events,大家好,这是我的第一个问题。 我在使自定义创建的单元格类上的单击事件正常工作时遇到一些问题。到目前为止,它会在单击单元格时发出通知,但它只显示最后一个单元格被单击,即使您单击了第一个单元格。这是我的密码 class Cell { public const int Width = 220; public const int Height = Width; public Point Position { get; set; } public string Id {
class Cell
{
public const int Width = 220;
public const int Height = Width;
public Point Position { get; set; }
public string Id { get; set; }
public delegate void ClickEvent(object o);
public event ClickEvent Click;
public Cell()
{
}
public void OnClick(Point p)
{
if (Click != null)
{
if (p.X - 220 < Position.X && p.X > 200 && p.Y - 220 < Position.Y && p.Y > 10)
{
Click(this);
}
}
}
public override string ToString() { return "Cell(" + row + "," + col + ")"; }
}
public partial class Form1 : Form
{
Grid myGrid;
Cell cell;
private Point userPoint;
Graphics g;
int x = 200;
int y = 20;
public Form1()
{
InitializeComponent();
myGrid = new Grid();
}
private void Form1_MouseDown(object sender, MouseEventArgs e)
{
userPoint = e.Location;
cell.OnClick(userPoint);
label1.Text = userPoint.ToString();
}
private void Form1_Paint(object sender, PaintEventArgs e)
{
g = e.Graphics;
DrawCrossingCells();
myGrid.DrawAllCrossings(g,imageList1);
}
private void DrawCrossingCells()
{
for (int row = 0; row < 3; row++)
{
for (int col = 0; col < 4; col++)
{
cell = new Cell(row,col);
g.DrawRectangle(new Pen(Color.Blue),x,y,Cell.Width,Cell.Height);
cell.Position = new Point(x, y);
cell.Id = (col.ToString() + row.ToString()).ToString();
x += 220;
cell.Click += cell_Click;
}
x = 200;
y += 220;
}
}
private void cell_Click(object sender)
{
Cell cc = (Cell)sender;
Crossing cross = new Crossing(cc.Id);
cross.Position = cc.Position;
myGrid.AddCrossing(cross);
MessageBox.Show(cc.Id);
}
}
类单元
{
公共const int Width=220;
公共const int高度=宽度;
公共点位置{get;set;}
公共字符串Id{get;set;}
公共委托无效点击事件(对象o);
公共事件点击事件点击;
公共单元格()
{
}
公共void OnClick(点p)
{
如果(单击!=null)
{
如果(p.X-220200&&p.Y-22010)
{
点击(这个);
}
}
}
公共重写字符串ToString(){return“Cell(“+row+”,“+col+”);}
}
公共部分类Form1:Form
{
网格myGrid;
细胞;
专用点用户点;
图形g;
int x=200;
int y=20;
公共表格1()
{
初始化组件();
myGrid=新网格();
}
私有void Form1\u MouseDown(对象发送方,MouseEventArgs e)
{
用户点=e.位置;
cell.OnClick(userPoint);
label1.Text=userPoint.ToString();
}
私有void Form1_Paint(对象发送器、PaintEventArgs e)
{
g=e.图形;
DrawCrossingCells();
myGrid.DrawAllCrossings(g,imageList1);
}
私有void DrawCrossingCells()
{
对于(int行=0;行<3;行++)
{
for(int col=0;col<4;col++)
{
单元=新单元(行、列);
g、 DrawRectangle(新笔(颜色为蓝色)、x、y、单元格宽度、单元格高度);
单元位置=新点(x,y);
cell.Id=(col.ToString()+row.ToString()).ToString();
x+=220;
单元格。单击+=单元格\u单击;
}
x=200;
y+=220;
}
}
专用空白单元格\u单击(对象发送者)
{
小区cc=(小区)发送方;
交叉口=新交叉口(cc.Id);
交叉位置=cc位置;
myGrid.AddCrossing(cross);
MessageBox.Show(cc.Id);
}
}
您只有一个单元格
对象,该对象在DrawCrossingCells
中循环的每次迭代中都会被覆盖。这意味着单元格
字段仅指向循环中创建的最后一个单元格
,因此当您执行cell.OnClick(userPoint)时
您总是在调用上次创建的单元格的OnClick
在表单1
中创建对象时,需要存储每个单元格
对象。行中每个单元格的列表
与每行列表
的列表
是有意义的。这意味着线单元代码>将变成列表单元格=新列表()代码>。然后,在循环中,您可以使用创建的每个单元格
填充单元格
对象
在Form1\u MouseDown
中,您需要确定单击了哪个单元格
,然后在正确的单元格上调用OnClick
。这可以通过将e.Location.X
除以220(单元格宽度)并将其用作内部List
的索引,将e.Location.Y
除以220(单元格高度)并使用其索引外部List
来实现
然后,两种更改方法的代码将为:
private void DrawCrossingCells()
{
for (int row = 0; row < 3; row++)
{
List<Cell> rowCells = new List<Cell>();
for (int col = 0; col < 4; col++)
{
Cell cell = new Cell(row, col);
g.DrawRectangle(new Pen(Color.Blue), x, y, Cell.Width, Cell.Height);
cell.Position = new Point(x, y);
cell.Id = (col.ToString() + row.ToString()).ToString();
x += 220;
cell.Click += cell_Click;
rowCells.Add(cell);
}
cells.Add(rowCells);
x = 0;
y += 220;
}
}
private void Form1_MouseDown(object sender, MouseEventArgs e)
{
int row = e.Location.Y / 220; //divide by the Y size
int column = e.Location.X / 220; //divide by the X size
cells[row][column].OnClick(e.Location);
label1.Text = e.Location.ToString();
}
private void DrawCrossingCells()
{
对于(int行=0;行<3;行++)
{
列表行单元格=新列表();
for(int col=0;col<4;col++)
{
单元格=新单元格(行、列);
g、 DrawRectangle(新笔(颜色为蓝色)、x、y、单元格宽度、单元格高度);
单元位置=新点(x,y);
cell.Id=(col.ToString()+row.ToString()).ToString();
x+=220;
单元格。单击+=单元格\u单击;
行单元格。添加(单元格);
}
单元格。添加(行单元格);
x=0;
y+=220;
}
}
私有void Form1\u MouseDown(对象发送方,MouseEventArgs e)
{
int row=e.Location.Y/220;//除以Y大小
int column=e.Location.X/220;//除以X的大小
单元格[行][列].OnClick(e.Location);
label1.Text=e.Location.ToString();
}
Is the Point in the Cell(单元内的点)部分感觉有点不对劲。试过使用矩形吗?看起来你在做一些数学运算,最终把它放到了其他地方,而不是你实际得到它的地方。你是说Cell类中Onclick方法的逻辑?因为我没有得到u。我认为Onclick
中的逻辑应该类似于if(p.X>Position.X&&p.XPosition.Y&&p.Y
。另外,在DrawCrossingCells
中,您正在将x
重置为200,以便第一行之后的行将从200开始。我认为应该是x=0
。问题是只有最后创建的单元格正在侦听事件,并且只有此单元格id显示在消息上啊,好的。您只有一个单元格
对象,在DrawCrossingCells
中循环的每次迭代中都会覆盖该对象,因此最后一个对象用于Form1\u MouseDown
。非常有用,非常感谢,现在我有另一个问题:我有一个最多12个交叉的图形,其中每个都有12条车道,你能给我推荐一个连接正确车道的最佳方法吗。正确地说,我的意思是通过id连接车道。id有三个字母-前两个字母表示它们所属的交叉口,第三个字母表示车道的实际数量。图形为二维数组(矩阵-12交叉口