从课堂上传递价值,以不同的形式表现出来以编程方式单击事件处理?

时间:2011-10-19 09:20:04

标签: c# winforms events class inheritance

香港专业教育学院目前已经创建了一个国际象棋棋盘,其中包含了各个部分的图像并且已经为棋盘着色等,我有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 + ")");
                }
        }
    }
}

4 个答案:

答案 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)

  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
               } 
         } 
    }
    
  2. 只需使用TextLabel的{​​{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;
    }
}

}