在 C# 中单击圆对象时如何移动它
How do you move a circle object when it is clicked on in C#
我正在尝试用 C# 制作跳棋。单击一块时我无法移动它。现在我只想让它移动到任何地方。它正在做的是在它需要移动时创建一个新的 piece 对象实例。任何帮助都会非常感谢。这是代码。
namespace ChineseCheckers
{
public partial class mainForm : Form
{
private Board thisBoard = new Board();
public event PaintEventHandler paint;
public mainForm()
{
InitializeComponent();
}
private void exitToolStripMenuItem_Click(object sender, EventArgs e)
{
Application.Exit();
}
private void mainForm_Paint(object sender, PaintEventArgs e)
{
int width = 15;
int del = 3;
int ystart = 50;
int xstart = ystart+4 * width;
SolidBrush whiteSB = new SolidBrush(Color.White);
for (int i = 0; i < 17; i++)
{
for (int j = 0; j < 17; j++)
{
if (Board.isSpace(i, j))
{
Space sp = thisBoard.getSpace(i, j);
int xPos = getXFromIndex(i, j, width, xstart, ystart);
int yPos = getYFromIndex(i, j, width, xstart, ystart);
pieceObject piece = new pieceObject(e, xPos - del, yPos - del, getColor(sp));
EventHandler myhandler = new EventHandler((a, b)=>myButton_Click(sender, e, piece));
piece.Click += myhandler;
piece.Size = new System.Drawing.Size(20, 20);
piece.Location = new System.Drawing.Point(xPos - del, yPos - del);
piece.BackColor = getColor(sp);
this.Controls.Add(piece);
}
}
}
}
private int getYFromIndex(int i, int j, int width, int xstart, int ystart)
{
return ystart + (2 * i) * width;
}
private int getIFromXY(int x, int y, int width, int xstart, int ystart)
{
return (y - ystart + width) / (2 * width);
}
private int getXFromIndex(int i, int j, int width, int xstart, int ystart)
{
return xstart + (2 * j - i) * width;
}
private int getJFromXY(int x, int y, int width, int xstart, int ystart)
{
int i = getIFromXY(x, y, width, xstart, ystart);
return (((x - xstart+ width/2) / width) + i) / 2;
}
private Color getColor(Space sp)
{
switch (sp)
{
case Space.Player1:
return Color.Orange;
case Space.Player2:
return Color.Yellow;
case Space.Player3:
return Color.Green;
case Space.Player4:
return Color.Blue;
case Space.Player5:
return Color.Purple;
case Space.Player6:
return Color.Red;
}
return Color.Gray;
}
private void newGameToolStripMenuItem_Click(object sender, EventArgs e)
{
Form currentForm = mainForm.ActiveForm;
currentForm.BackgroundImage = null;
currentForm.BackColor = Color.Black;
currentForm.Width = 600;
currentForm.Height = 650;
Button endTurn = new Button();
endTurn.Location = new Point(485, 575);
endTurn.Text = "End Turn";
endTurn.BackColor = Color.Wheat;
endTurn.Click += new EventHandler(endTurnEvent);
this.Controls.Add(endTurn);
}
public void endTurnEvent(object sender, EventArgs e)
{
System.Console.WriteLine("You have ended your turn!");
}
private void mainForm_MouseClick(object sender, MouseEventArgs e)
{
}
void myButton_Click(Object sender, System.EventArgs e, pieceObject piece)
{
System.Console.WriteLine("Position: " + piece.Location + "Color: " + piece.BackColor);
piece.Location = new Point(40, 40);
}
}
}
public class pieceObject : UserControl
{
// Draw the new button.
public pieceObject(PaintEventArgs e, int xPos, int yPos, Color color)
{
int width = 15;
SolidBrush whiteSB = new SolidBrush(color);
SolidBrush newPiece = new SolidBrush(color);
e.Graphics.FillEllipse(newPiece, xPos, yPos, width, width);
newPiece.Dispose();
}
}
没有 a good, minimal, complete code example 就不可能确定最好的建议是什么。但是考虑到你的问题陈述:
What it is doing is creating a new instance of the piece object when it needs to just move
…至少可以确定导致该错误的具体错误并提供一些建议。
您获得 pieceObject
class 的新实例的原因是您在每次引发表单的 Paint
事件时创建它们。重要的是要了解 Paint
事件在每次 Windows 决定 window 需要重绘时引发 。这不是一次性的事情。
根据您目前在设计方面的方向,您似乎真的只希望您放入 Paint
事件处理程序中的代码只执行一次。如果是这样,我建议按如下方式更改代码:
首先,修复 pieceObject
以便它根据需要自行绘制:
public class pieceObject : UserControl
{
private readonly Color _color;
public pieceObject(Color color) { _color = color; }
// Draw the new button.
protected override void OnPaint(PaintEventArgs e)
{
int width = 15;
using (SolidBrush newPiece = new SolidBrush(_color))
{
e.Graphics.FillEllipse(newPiece, 3, 3, width, width);
}
}
}
然后,不要在每次引发表单的 Paint
事件时都创建 pieceObject
实例,只需在创建表单时创建一次:
public mainForm()
{
InitializeComponent();
InitializePieceControls();
}
private void InitializePieceControls()
{
int width = 15;
int del = 3;
int ystart = 50;
int xstart = ystart+4 * width;
for (int i = 0; i < 17; i++)
{
for (int j = 0; j < 17; j++)
{
if (Board.isSpace(i, j))
{
Space sp = thisBoard.getSpace(i, j);
int xPos = getXFromIndex(i, j, width, xstart, ystart);
int yPos = getYFromIndex(i, j, width, xstart, ystart);
pieceObject piece = new pieceObject(getColor(sp));
piece.Click += myButton_Click;
piece.Size = new System.Drawing.Size(20, 20);
piece.Location = new System.Drawing.Point(xPos - del, yPos - del);
// It's not clear why you are doing this, as it will just make
// it impossible to see the ellipse that is drawn by the piece
// itself
piece.BackColor = getColor(sp);
this.Controls.Add(piece);
}
}
}
}
void myButton_Click(object sender, EventArgs e)
{
pieceObject piece = (pieceObject)sender;
System.Console.WriteLine("Position: " + piece.Location + "Color: " + piece.BackColor);
piece.Location = new Point(40, 40);
}
备注:
- 在上面我还删除了几个地方你创建了一个白色的画笔,没有使用它,然后没有处理它。
- 您在
pieceObject
上使用 Click
事件在几个方面是错误的:首先,lambda 表达式捕获了 Paint
事件的发送者和事件参数,不是随事件实际发送的 a
和 b
;其次,首先不需要将事件处理程序包装在 lambda 中,因为您可以将 Click
事件的实际 sender
转换为实际上的 pieceObject
发送事件。
我正在尝试用 C# 制作跳棋。单击一块时我无法移动它。现在我只想让它移动到任何地方。它正在做的是在它需要移动时创建一个新的 piece 对象实例。任何帮助都会非常感谢。这是代码。
namespace ChineseCheckers
{
public partial class mainForm : Form
{
private Board thisBoard = new Board();
public event PaintEventHandler paint;
public mainForm()
{
InitializeComponent();
}
private void exitToolStripMenuItem_Click(object sender, EventArgs e)
{
Application.Exit();
}
private void mainForm_Paint(object sender, PaintEventArgs e)
{
int width = 15;
int del = 3;
int ystart = 50;
int xstart = ystart+4 * width;
SolidBrush whiteSB = new SolidBrush(Color.White);
for (int i = 0; i < 17; i++)
{
for (int j = 0; j < 17; j++)
{
if (Board.isSpace(i, j))
{
Space sp = thisBoard.getSpace(i, j);
int xPos = getXFromIndex(i, j, width, xstart, ystart);
int yPos = getYFromIndex(i, j, width, xstart, ystart);
pieceObject piece = new pieceObject(e, xPos - del, yPos - del, getColor(sp));
EventHandler myhandler = new EventHandler((a, b)=>myButton_Click(sender, e, piece));
piece.Click += myhandler;
piece.Size = new System.Drawing.Size(20, 20);
piece.Location = new System.Drawing.Point(xPos - del, yPos - del);
piece.BackColor = getColor(sp);
this.Controls.Add(piece);
}
}
}
}
private int getYFromIndex(int i, int j, int width, int xstart, int ystart)
{
return ystart + (2 * i) * width;
}
private int getIFromXY(int x, int y, int width, int xstart, int ystart)
{
return (y - ystart + width) / (2 * width);
}
private int getXFromIndex(int i, int j, int width, int xstart, int ystart)
{
return xstart + (2 * j - i) * width;
}
private int getJFromXY(int x, int y, int width, int xstart, int ystart)
{
int i = getIFromXY(x, y, width, xstart, ystart);
return (((x - xstart+ width/2) / width) + i) / 2;
}
private Color getColor(Space sp)
{
switch (sp)
{
case Space.Player1:
return Color.Orange;
case Space.Player2:
return Color.Yellow;
case Space.Player3:
return Color.Green;
case Space.Player4:
return Color.Blue;
case Space.Player5:
return Color.Purple;
case Space.Player6:
return Color.Red;
}
return Color.Gray;
}
private void newGameToolStripMenuItem_Click(object sender, EventArgs e)
{
Form currentForm = mainForm.ActiveForm;
currentForm.BackgroundImage = null;
currentForm.BackColor = Color.Black;
currentForm.Width = 600;
currentForm.Height = 650;
Button endTurn = new Button();
endTurn.Location = new Point(485, 575);
endTurn.Text = "End Turn";
endTurn.BackColor = Color.Wheat;
endTurn.Click += new EventHandler(endTurnEvent);
this.Controls.Add(endTurn);
}
public void endTurnEvent(object sender, EventArgs e)
{
System.Console.WriteLine("You have ended your turn!");
}
private void mainForm_MouseClick(object sender, MouseEventArgs e)
{
}
void myButton_Click(Object sender, System.EventArgs e, pieceObject piece)
{
System.Console.WriteLine("Position: " + piece.Location + "Color: " + piece.BackColor);
piece.Location = new Point(40, 40);
}
}
}
public class pieceObject : UserControl
{
// Draw the new button.
public pieceObject(PaintEventArgs e, int xPos, int yPos, Color color)
{
int width = 15;
SolidBrush whiteSB = new SolidBrush(color);
SolidBrush newPiece = new SolidBrush(color);
e.Graphics.FillEllipse(newPiece, xPos, yPos, width, width);
newPiece.Dispose();
}
}
没有 a good, minimal, complete code example 就不可能确定最好的建议是什么。但是考虑到你的问题陈述:
What it is doing is creating a new instance of the piece object when it needs to just move
…至少可以确定导致该错误的具体错误并提供一些建议。
您获得 pieceObject
class 的新实例的原因是您在每次引发表单的 Paint
事件时创建它们。重要的是要了解 Paint
事件在每次 Windows 决定 window 需要重绘时引发 。这不是一次性的事情。
根据您目前在设计方面的方向,您似乎真的只希望您放入 Paint
事件处理程序中的代码只执行一次。如果是这样,我建议按如下方式更改代码:
首先,修复 pieceObject
以便它根据需要自行绘制:
public class pieceObject : UserControl
{
private readonly Color _color;
public pieceObject(Color color) { _color = color; }
// Draw the new button.
protected override void OnPaint(PaintEventArgs e)
{
int width = 15;
using (SolidBrush newPiece = new SolidBrush(_color))
{
e.Graphics.FillEllipse(newPiece, 3, 3, width, width);
}
}
}
然后,不要在每次引发表单的 Paint
事件时都创建 pieceObject
实例,只需在创建表单时创建一次:
public mainForm()
{
InitializeComponent();
InitializePieceControls();
}
private void InitializePieceControls()
{
int width = 15;
int del = 3;
int ystart = 50;
int xstart = ystart+4 * width;
for (int i = 0; i < 17; i++)
{
for (int j = 0; j < 17; j++)
{
if (Board.isSpace(i, j))
{
Space sp = thisBoard.getSpace(i, j);
int xPos = getXFromIndex(i, j, width, xstart, ystart);
int yPos = getYFromIndex(i, j, width, xstart, ystart);
pieceObject piece = new pieceObject(getColor(sp));
piece.Click += myButton_Click;
piece.Size = new System.Drawing.Size(20, 20);
piece.Location = new System.Drawing.Point(xPos - del, yPos - del);
// It's not clear why you are doing this, as it will just make
// it impossible to see the ellipse that is drawn by the piece
// itself
piece.BackColor = getColor(sp);
this.Controls.Add(piece);
}
}
}
}
void myButton_Click(object sender, EventArgs e)
{
pieceObject piece = (pieceObject)sender;
System.Console.WriteLine("Position: " + piece.Location + "Color: " + piece.BackColor);
piece.Location = new Point(40, 40);
}
备注:
- 在上面我还删除了几个地方你创建了一个白色的画笔,没有使用它,然后没有处理它。
- 您在
pieceObject
上使用Click
事件在几个方面是错误的:首先,lambda 表达式捕获了Paint
事件的发送者和事件参数,不是随事件实际发送的a
和b
;其次,首先不需要将事件处理程序包装在 lambda 中,因为您可以将Click
事件的实际sender
转换为实际上的pieceObject
发送事件。