香港专业教育学院目前已经创建了一个国际象棋棋盘,其中包含了各个部分的图像并且已经为棋盘着色等,我有2个问题,我希望你可以帮助我点击事件方法?单击一个正方形时,我当前的方法会更改sqaure颜色,并显示一个消息框,显示xy坐标和块的类型,如果它没有被一个块占用,则只是坐标:
问题1:如果我再次点击相同的sqaure或不同的sqaure,我怎样才能让颜色变回原来的颜色?
问题2:我如何代替显示meesagebox,在文本框或标签中显示Form1.cs上的信息?
以下是我的GridSqaure.cs类的代码:
namespace Chess
{
public class GridSquare : PictureBox
{
private int x;
private int y;
private ChessPiece piece;
public int X { get { return x; } }
public int Y { get { return y; } }
public ChessPiece Piece
{
get { return piece; }
set
{
piece = value;
if (value == null)
this.BackgroundImage = null;
else
this.BackgroundImage = piece.GetImage();
}
}
public GridSquare(int x, int y)
{
int ButtonWidth = 64;
int ButtonHeight = 64;
int Distance = 20;
int start_x = 10;
int start_y = 10;
this.x = x;
this.y = y;
this.Top = start_x + (x * ButtonHeight + Distance + x);
this.Left = start_y + (y * ButtonWidth + Distance + y);
this.Width = ButtonWidth;
this.Height = ButtonHeight;
this.Text = "X: " + x.ToString() + " Y: " + y.ToString();
this.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle;
this.Click += new System.EventHandler(gridSquare_Click);
}
private void gridSquare_Click(object sender, EventArgs e)
{
GridSquare gs = (GridSquare)sender;
if (gs.Piece != null)
{
//Change: need to show xy of sqaure clicked on a label or textbox on the main window.
MessageBox.Show("You clicked a " + gs.Piece.GetName() + " at (" + gs.X + ", " + gs.Y + ")");
//Change: need to click for change in colour, then second click to revert back
this.BackColor = Color.LightBlue;
}
else
{
//Change: need to show xy of clicked square but including meesage stating the sqaure needs to be occupied by a piece.
MessageBox.Show("You clicked (" + gs.X + ", " + gs.Y + ")");
}
}
}
}
答案 0 :(得分:2)
我会避免让一个类处理它自己的一个事件。这不是一个好习惯。
相反,我会使用回调策略。
首先,像这样重新编码GridSquare
:
public class GridSquare : PictureBox
{
/* As before */
public GridSquare(int x, int y, Action<GridSquare> clicked)
{
/* As before */
this.Click += (s, e) => clicked(this);
}
/* NO private void gridSquare_Click(object sender, EventArgs e) */
}
现在由调用代码来完成这项艰苦的工作。
我假设您正在使用嵌套for循环创建电路板,这些循环将每个创建的GridSquare
添加到表单的Controls
集合中。如果是这种情况,您需要编写如下代码:
for (var x = 0; x < 8; x++)
{
for (var y = 0; y < 8; y++)
{
this.Controls.Add(new GridSquare(x, y, clicked));
}
}
现在您只需要定义clicked
- 点击每个GridSquare
时的回调 - 该代码如下所示:
GridSquare lastClicked = null;
Color lastBackColor = Color.Transparent;
Action<GridSquare> clicked = gs =>
{
lastClicked.BackColor = lastBackColor;
if (!lastClicked.Equals(gs))
{
lastClicked = gs;
lastBackColor = gs.BackColor;
gs.BackColor = Color.LightBlue;
var inner = gs.Piece != null
? String.Format("a {0} at ", gs.Piece.GetName())
: "";
var msg = String.Format("You clicked {0}({1}, {2})", inner, gs.X, gs.Y);
MessageBox.Show(msg);
}
};
显然,此代码在创建网格方块之前进行。
这应该相对容易理解,但如果没有,请问,我会详细说明。
请告诉我这是否适合您。
答案 1 :(得分:1)
首先将盒子的实际颜色存储在Color类的对象中,假设对象名称为“BoxColor”,现在看到以下代码。
if (gs.Piece != null)
{
//Change: need to show xy of sqaure clicked on a label or textbox on the main window.
label1.Text = "You clicked a " + gs.Piece.GetName() + " at (" + gs.X + ", " + gs.Y + ")";
//Change: need to click for change in colour, then second click to revert back
this.BackColor = Color.LightBlue;
}
else
{
//Change: need to show xy of clicked square but including meesage stating the sqaure needs to be occupied by a piece.
this.BackColor = BoxColor //setting back the original color if the box is clicked again.
label1.Text = "You clicked (" + gs.X + ", " + gs.Y + ")";
}
并且只有当盒子的颜色从其实际颜色改变时才设置一个布尔变量,现在如果用户点击任何其他盒子,则检查这些标志,如果真实,则重置颜色。
答案 2 :(得分:1)
您可以在班级boolean
的范围内创建GridSquare
变量。然后在gridSquare_Click
事件处理程序上使用此变量,如下所示:
public class GridSquare : PictureBox
{
bool isFirstClick = true;
.....
.....
.....
private void gridSquare_Click(object sender, EventArgs e)
{
if(isFirstClick)
{
isFirstClick = false;
//Set one color
}
else
{
isFirstClick = true;
//Set other color
}
}
}
只需使用Text
或Label
的{{1}}属性。
答案 3 :(得分:0)
这是我对原始代码的修正:
namespace Chess
{
public class GridSquare : PictureBox
{
private int x;
private int y;
private static GridSquare lastClicked;
private static ChessBoard board;
private ChessPiece piece;
public int X { get { return x; } }
public int Y { get { return y; } }
public static ChessBoard Board { set { board = value; } }
Color LightTile = Color.Beige;
Color DarkTile = Color.SandyBrown;
public ChessPiece Piece
{
get { return piece; }
set
{
piece = value;
if (value == null)
this.BackgroundImage = null;
else
this.BackgroundImage = piece.GetImage();
}
}
public GridSquare(int x, int y)
{
int ButtonWidth = 64;
int ButtonHeight = 64;
int Distance = 20;
int start_x = 10;
int start_y = 10;
this.x = x;
this.y = y;
this.Top = start_x + (x * ButtonHeight + Distance + x);
this.Left = start_y + (y * ButtonWidth + Distance + y);
this.Width = ButtonWidth;
this.Height = ButtonHeight;
this.Text = "X: " + x.ToString() + " Y: " + y.ToString();
this.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle;
this.Click += new System.EventHandler(gridSquare_Click);
}
private void gridSquare_Click(object sender, EventArgs e)
{
GridSquare gs = (GridSquare)sender;
if (lastClicked != null)
lastClicked.ResetColour();
//Change: need to click for change in colour, then second click to revert back
this.BackColor = Color.LightBlue;
lastClicked = this;
if (gs.Piece != null)
{
board.StatusLabel.Text = "You clicked a " + gs.Piece.GetName() + " at (" + gs.X + ", " + gs.Y + ")";
}
else
{
board.StatusLabel.Text = "You clicked (" + gs.X + ", " + gs.Y + ")";
}
}
public void ResetColour()
{
if (x % 2 == 0)
if (y % 2 == 0)
// If x=Even y=Even
this.BackColor = LightTile;
else
// If x=Even y=Odd
this.BackColor = DarkTile;
else
if (y % 2 == 0)
// If x=Odd y=Even
this.BackColor = DarkTile;
else
// If x=Odd y=Odd
this.BackColor = LightTile;
}
}
}