-3

当我运行以下代码时,它会填充label1一次控件。然后label1控件什么也不做。如何让label1控件更改鼠标输入事件。请提供代码示例。

    int currentXposition, currentYposition;
    const string positionLabel = "Current Position: ";

    private void Test_Load(object sender, EventArgs a)
    {
        var temp=Color.Transparent;    //Used to store the old color name of the panels before mouse events
        var colorName = Color.Red;      //Color used to highlight panel when mouse over
        int numBlocks = 8;             //Used to hold the number of blocks per row
        int blockSize=70;

        //Initialize new array of Panels  new
        string[,] Position = new string[8, 8];
        Panel[,] chessBoardPanels = new Panel[numBlocks, numBlocks];
        string Alphabet = "A,B,C,D,E,F,G,H";
        string Numbers ="1,2,3,4,5,6,7,8";
        string[] alphaStrings = Alphabet.Split(',');
        string[] numStrings=Numbers.Split(',');
        // b = sub[0];
        int FirstValue, SecondValue;

        //Store Position Values
        for (int firstValue = 0; firstValue < 8; ++firstValue)
        {
            FirstValue = Alphabet[firstValue];
            for (int SecValue = 0; SecValue < 8; ++SecValue)
            {
                SecondValue = Numbers[SecValue];
                Position[firstValue, SecValue] = alphaStrings[firstValue] + numStrings[SecValue];
            }
        }

        //Loop to create panels
        for (int iRow = 0; iRow < numBlocks; iRow++)
        {
            for (int iColumn = 0; iColumn < numBlocks; iColumn++)
            {
                Panel p = new Panel();
                //set size
                p.Size = new Size(blockSize, blockSize);
                //set back colour
                p.BackColor = (iRow + (iColumn % 2)) % 2 == 0 ? Color.Black : Color.White;
                //set location
                p.Location = new Point(blockSize *iRow+15, blockSize * iColumn+15);
                chessBoardPanels[iRow, iColumn] = p;
                chessBoardPanels[iRow,iColumn].MouseEnter += (s,e) =>
                {
                    currentXposition = iRow;
                    currentYposition = iColumn;

                    var oldColor = (s as Panel).BackColor;
                    (s as Panel).BackColor = colorName;
                    temp = oldColor;
                    label1.Text = Position[iRow, iColumn];
                };

                chessBoardPanels[iRow, iColumn].MouseLeave += (s, e) => {
                    (s as Panel).BackColor = temp;
                };
                groupBox1.Controls.Add(p);
            }
        }
    }
4

1 回答 1

0

我之所以回答这个问题,只是因为我认为展示范围混淆时会发生什么很重要。您遇到问题的原因是变量的范围。您的标签正在改变iRow * iColumn时代,但仅限于初始执行期间。从那时起,iRowiColumn固定在它们的最终值。

为了实现您想要的最终目标,创建面板的扩展是最简单的:

public class ChessPanel : Panel {

     private const Color HighlightColor = Color.Red;


     public int iColumn { get; set; }
     public int iRow { get; set; }
     public Color PrimaryColor { get; set; }

     public ChessPanel() : base()
     {
        this.MouseEnter += (s,e) =>
                {
                    this.PrimaryColor = this.BackColor;
                    this.BackColor = HighlightColor;
                };

         this.MouseLeave += (s,e) => 
                {
                    this.BackColor = this.PrimaryColor;
                };
     }     

}    

然后,这将允许您减少代码,如下所示:

int currentXposition, currentYposition;
const string positionLabel = "Current Position: ";

private void Test_Load(object sender, EventArgs a)
{
    var temp=Color.Transparent;    //Used to store the old color name of the panels before mouse events
    var colorName = Color.Red;      //Color used to highlight panel when mouse over
    int numBlocks = 8;             //Used to hold the number of blocks per row
    int blockSize=70;

    //Initialize new array of Panels  new
    string[,] Position = new string[8, 8];
    ChessPanel[,] chessBoardPanels = new ChessPanel[numBlocks, numBlocks];
    string Alphabet = "A,B,C,D,E,F,G,H";
    string Numbers ="1,2,3,4,5,6,7,8";
    string[] alphaStrings = Alphabet.Split(',');
    string[] numStrings=Numbers.Split(',');
    int FirstValue, SecondValue;

    //Store Position Values --- no idea what this is supposed to do...
    for (int firstValue = 0; firstValue < 8; ++firstValue)
    {
        FirstValue = Alphabet[firstValue];
        for (int SecValue = 0; SecValue < 8; ++SecValue)
        {
            SecondValue = Numbers[SecValue];
            Position[firstValue, SecValue] = alphaStrings[firstValue] + numStrings[SecValue];
        }
    }

    //Loop to create panels
    for (int iRow = 0; iRow < numBlocks; iRow++)
    {
        for (int iColumn = 0; iColumn < numBlocks; iColumn++)
        {
            ChessPanel p = new ChessPanel();
            //set size
            p.Size = new Size(blockSize, blockSize);
            //set back colour
            p.BackColor = (iRow + (iColumn % 2)) % 2 == 0 ? Color.Black : Color.White;
            //set location
            p.Location = new Point(blockSize *iRow+15, blockSize * iColumn+15);

            p.MouseEnter += (s,e) =>
            {
                var cpSelf = s as ChessPanel;
                if (cpSelf != null)
                {
                    label1.Text = Position[cpSelf.iRow, cpSelf.iColumn];
                }
            };

            groupBox1.Controls.Add(p);
            chessBoardPanels[iRow, iColumn] = p;
        }
    }
}

我假设您稍后在程序中使用了许多这些变量,并且看着这种让我头疼的东西,所以我把大部分留在原地。

委托是一个非常强大和有用的实用程序,但它们可能会导致与变量范围混淆。使用这些时要非常小心,并确保将它们视为稍后执行的功能单元,因此只能依赖于块执行时的程序状态,而不是创建块时的状态。如果您注意到,我保留对Position数组的引用只是为了表明您仍然可以访问委托范围内的局部变量,因为它在技术上仍在范围内。从结构上讲,这可以很容易地移入 ChessPanel 类并在本地 100% 引用。这个例子应该谨慎使用,因为它可以显示许多人认为在函数执行结束时被垃圾收集的“本地”变量如何徘徊并消耗内存。

此代码未经测试,可能有轻微的语法错误。希望结构的精神得到理解。

于 2013-09-12T14:18:31.190 回答