передать значение из класса, чтобы показать в другой форме и обработать событие щелчка программно? - PullRequest
1 голос
/ 19 октября 2011

В настоящее время я создал шахматную доску с изображениями фигур на месте и раскрасил доску и т. Д. У меня есть 2 проблемы с методом события щелчка, который, надеюсь, вы могли бы мне помочь? при щелчке по квадрату мой текущий метод меняет цвет sqaure и отображает окно сообщения, показывающее координаты xy и тип элемента или просто координаты, если элемент не занят:

Проблема 1: Как я могу вернуть цвет к исходному, если я снова нажму на тот же квадрат или другой квадрат?

Проблема 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 ]

2 голосов
/ 19 октября 2011

Я бы избегал, чтобы класс обрабатывал одно из своих собственных событий.Это не очень хорошая практика.

Вместо этого я бы использовал стратегию обратного вызова.

Во-первых, перекодируйте 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) */
}

Теперь этодо вызывающего кода для выполнения тяжелой работы.

Я предполагаю, что вы создаете доску, используя что-то вроде вложенных циклов, которые добавляют каждый созданный 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 голос
/ 19 октября 2011
  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. Просто используйте Text свойство Label или TextBox.

1 голос
/ 19 октября 2011

Сначала сохраните фактический цвет блока в объекте класса 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 + ")";     
} 

А также включите одну булеву переменную, чтобы она включалась только тогда, когда цвет блока изменяется с его фактического цвета, а теперь, если пользователь нажимает на любые другие поля, проверяет наличие этих флагов, и если его значение true, сбрасывает цвет.

0 голосов
/ 20 октября 2011

Это то, что я изменил свой оригинальный код:

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;
    }
}

}

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...