如何在 c# winform 中将面板拆分为可点击的段?

我正在尝试用 c# 模拟 LED 显示板。我需要一个control包含 1536 个可点击的controls 来模拟 LED(宽度为 96,高度为 16)。我为此使用了一个panel命名pnlContainer,用户将panel在运行时添加 1536 个微小的自定义s。这些自定义的panels 应该在运行时通过单击事件更改它们的颜色。一切正常。但是将这个数量的 tiny panels添加到容器需要很长时间(大约 10 秒)。你有什么建议来解决这个问题?任何提示表示赞赏。


这是我的客户panel:


public partial class LedPanel : Panel

{

    public LedPanel()

    {

        InitializeComponent();

    }


    protected override void OnPaint(PaintEventArgs pe)

    {

        base.OnPaint(pe);


    }


    protected override void OnMouseDown(MouseEventArgs e)

    {

        if (e.Button == MouseButtons.Left)

        {

            if (this.BackColor == Color.Black)

            {

                this.BackColor = Color.Red;

            }

            else

            {

                this.BackColor = Color.Black;

            }

        }

    }

}

这是一段代码,它添加了小panels 到pnlContainer:


private void getPixels(Bitmap img2)

    {


        pnlContainer.Controls.Clear();


        for (int i = 0; i < 96; i++)

        {

            for (int j = 0; j < 16; j++)

            {


                Custom_Controls.LedPanel led = new Custom_Controls.LedPanel();

                led.Name = i.ToString() + j.ToString();

                int lWidth = (int)(pnlContainer.Width / 96);

                led.Left = i * lWidth;

                led.Top = j * lWidth;

                led.Width = led.Height = lWidth;

                if (img2.GetPixel(i, j).R>numClear.Value)

                {

                    led.BackColor = Color.Red;

                }

                else

                {

                    led.BackColor = Color.Black;

                }

                led.BorderStyle = BorderStyle.FixedSingle;



                pnlContainer.Controls.Add(led);


            }

        }


    }

http://img.mukewang.com/61ac809300010cb907880644.jpg

ABOUTYOU
浏览 242回答 2
2回答

慕尼黑5688855

我同意@TaW 的建议。不要在一个表单上放置 1000 多个控件。使用某种数据结构,如数组来跟踪哪些 LED 需要点亮,然后在面板的 Paint 事件中绘制它们。这是一个例子。将面板放在窗体上并将其命名为ledPanel。然后使用类似于以下的代码。我只是随机设置布尔数组的值。您需要适当地设置它们以响应单击鼠标。我没有包含该代码,但基本上您需要获取鼠标单击的位置,确定需要设置(或取消设置)哪个数组条目,然后使面板无效,以便它重新绘制自己。public partial class Form1 : Form{&nbsp; &nbsp; //set these variables appropriately&nbsp; &nbsp; int matrixWidth = 96;&nbsp; &nbsp; int matrixHeight = 16;&nbsp; &nbsp; //An array to hold which LEDs must be lit&nbsp; &nbsp; bool[,] ledMatrix = null;&nbsp; &nbsp; //Used to randomly populate the LED array&nbsp; &nbsp; Random rnd = new Random();&nbsp; &nbsp; public Form1()&nbsp; &nbsp; {&nbsp; &nbsp; &nbsp; &nbsp; InitializeComponent();&nbsp; &nbsp; &nbsp; &nbsp; ledPanel.BackColor = Color.Black;&nbsp; &nbsp; &nbsp; &nbsp; ledPanel.Resize += LedPanel_Resize;&nbsp; &nbsp; &nbsp; &nbsp; //clear the array by initializing a new one&nbsp; &nbsp; &nbsp; &nbsp; ledMatrix = new bool[matrixWidth, matrixHeight];&nbsp; &nbsp; &nbsp; &nbsp; //Force the panel to repaint itself&nbsp; &nbsp; &nbsp; &nbsp; ledPanel.Invalidate();&nbsp; &nbsp; }&nbsp; &nbsp; private void LedPanel_Resize(object sender, EventArgs e)&nbsp; &nbsp; {&nbsp; &nbsp; &nbsp; &nbsp; //If the panel resizes, then repaint.&nbsp;&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; ledPanel.Invalidate();&nbsp; &nbsp; }&nbsp; &nbsp; private void button1_Click(object sender, EventArgs e)&nbsp; &nbsp; {&nbsp; &nbsp; &nbsp; &nbsp; //clear the array by initializing a new one&nbsp; &nbsp; &nbsp; &nbsp; ledMatrix = new bool[matrixWidth, matrixHeight];&nbsp; &nbsp; &nbsp; &nbsp; //Randomly set 250 of the 'LEDs';&nbsp; &nbsp; &nbsp; &nbsp; for (int i = 0; i < 250; i++)&nbsp; &nbsp; &nbsp; &nbsp; {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; ledMatrix[rnd.Next(0, matrixWidth), rnd.Next(0, matrixHeight)] = true;&nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; &nbsp; &nbsp; //Make the panel repaint itself&nbsp; &nbsp; &nbsp; &nbsp; ledPanel.Invalidate();&nbsp; &nbsp; }&nbsp; &nbsp; private void ledPanel_Paint(object sender, PaintEventArgs e)&nbsp; &nbsp; {&nbsp; &nbsp; &nbsp; &nbsp; //Calculate the width and height of each LED based on the panel width&nbsp; &nbsp; &nbsp; &nbsp; //and height and allowing for a line between each LED&nbsp; &nbsp; &nbsp; &nbsp; int cellWidth = (ledPanel.Width - 1) / (matrixWidth + 1);&nbsp; &nbsp; &nbsp; &nbsp; int cellHeight = (ledPanel.Height - 1) / (matrixHeight + 1);&nbsp; &nbsp; &nbsp; &nbsp; //Loop through the boolean array and draw a filled rectangle&nbsp; &nbsp; &nbsp; &nbsp; //for each one that is set to true&nbsp; &nbsp; &nbsp; &nbsp; for (int i = 0; i < matrixWidth; i++)&nbsp; &nbsp; &nbsp; &nbsp; {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; for (int j = 0; j < matrixHeight; j++)&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; if (ledMatrix != null)&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; //I created a custom brush here for the 'off' LEDs because none&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; //of the built in colors were dark enough for me. I created it&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; //in a using block because custom brushes need to be disposed.&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; using (var b = new SolidBrush(Color.FromArgb(64, 0, 0)))&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; //Determine which brush to use depending on if the LED is lit&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Brush ledBrush = ledMatrix[i, j] ? Brushes.Red : b;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; //Calculate the top left corner of the rectangle to draw&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; var x = (i * (cellWidth + 1)) + 1;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; var y = (j * (cellHeight + 1) + 1);&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; //Draw a filled rectangle&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; e.Graphics.FillRectangle(ledBrush, x, y, cellWidth, cellHeight);&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; }&nbsp; &nbsp; private void ledPanel_MouseUp(object sender, MouseEventArgs e)&nbsp; &nbsp; {&nbsp; &nbsp; &nbsp; &nbsp; //Get the cell width and height&nbsp; &nbsp; &nbsp; &nbsp; int cellWidth = (ledPanel.Width - 1) / (matrixWidth + 1);&nbsp; &nbsp; &nbsp; &nbsp; int cellHeight = (ledPanel.Height - 1) / (matrixHeight + 1);&nbsp; &nbsp; &nbsp; &nbsp; //Calculate which LED needs to be turned on or off&nbsp; &nbsp; &nbsp; &nbsp; int x = e.Location.X / (cellWidth + 1);&nbsp; &nbsp; &nbsp; &nbsp; int y = e.Location.Y / (cellHeight + 1);&nbsp; &nbsp; &nbsp; &nbsp; //Toggle that LED.&nbsp; If it's off, then turn it on and if it's on,&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; //turn it off&nbsp; &nbsp; &nbsp; &nbsp; ledMatrix[x, y] = !ledMatrix[x, y];&nbsp; &nbsp; &nbsp; &nbsp; //Force the panel to update itself.&nbsp; &nbsp; &nbsp; &nbsp; ledPanel.Invalidate();&nbsp; &nbsp; }}我相信这段代码可以有很多改进,但它应该让你知道如何去做。

慕的地6264312

这是一个类似于@Chris 的代码,但将显示逻辑隔离在一个单独的类中。(@Chris 在我编写代码时回答了您的问题 :))))只需创建一个二维数组来初始化类并将其传递给 Initialize 方法。&nbsp; &nbsp; public class LedDisplayer&nbsp; &nbsp; {&nbsp; &nbsp; &nbsp; &nbsp; public LedDisplayer(Control control)&nbsp; &nbsp; &nbsp; &nbsp; {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; _control = control;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; _control.MouseDown += MouseDown;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; _control.Paint += Control_Paint;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; // width and height of your tiny boxes&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; _width = 5;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; _height = 5;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; // margin between tiny boxes&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; _margin = 1;&nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; &nbsp; &nbsp; private readonly Control _control;&nbsp; &nbsp; &nbsp; &nbsp; private readonly int _width;&nbsp; &nbsp; &nbsp; &nbsp; private readonly int _height;&nbsp; &nbsp; &nbsp; &nbsp; private readonly int _margin;&nbsp; &nbsp; &nbsp; &nbsp; private bool[,] _values;&nbsp; &nbsp; &nbsp; &nbsp; // call this method first of all to initialize the Displayer&nbsp; &nbsp; &nbsp; &nbsp; public void Initialize(bool[,] values)&nbsp; &nbsp; &nbsp; &nbsp; {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; _values = values;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; _control.Invalidate();&nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; &nbsp; &nbsp; private void MouseDown(object sender, MouseEventArgs e)&nbsp; &nbsp; &nbsp; &nbsp; {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; var firstIndex = e.X / OuterWidth();&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; var secondIndex = e.Y / OuterHeight();&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; _values[firstIndex, secondIndex] = !_values[firstIndex, secondIndex];&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; _control.Invalidate(); // you can use other overloads of Invalidate method for the blink problem&nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; &nbsp; &nbsp; private void Control_Paint(object sender, PaintEventArgs e)&nbsp; &nbsp; &nbsp; &nbsp; {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; if (_values == null)&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; return;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; e.Graphics.Clear(_control.BackColor);&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; for (int i = 0; i < _values.GetLength(0); i++)&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; for (int j = 0; j < _values.GetLength(1); j++)&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Rectangle(i, j).Paint(e.Graphics);&nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; &nbsp; &nbsp; private RectangleInfo Rectangle(int firstIndex, int secondIndex)&nbsp; &nbsp; &nbsp; &nbsp; {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; var x = firstIndex * OuterWidth();&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; var y = secondIndex * OuterHeight();&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; var rectangle = new Rectangle(x, y, _width, _height);&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; if (_values[firstIndex, secondIndex])&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; return new RectangleInfo(rectangle, Brushes.Red);&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; return new RectangleInfo(rectangle, Brushes.Black);&nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; &nbsp; &nbsp; private int OuterWidth()&nbsp; &nbsp; &nbsp; &nbsp; {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; return _width + _margin;&nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; &nbsp; &nbsp; private int OuterHeight()&nbsp; &nbsp; &nbsp; &nbsp; {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; return _height + _margin;&nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; }&nbsp; &nbsp; public class RectangleInfo&nbsp; &nbsp; {&nbsp; &nbsp; &nbsp; &nbsp; public RectangleInfo(Rectangle rectangle, Brush brush)&nbsp; &nbsp; &nbsp; &nbsp; {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Rectangle = rectangle;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Brush = brush;&nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; &nbsp; &nbsp; public Rectangle Rectangle { get; }&nbsp; &nbsp; &nbsp; &nbsp; public Brush Brush { get; }&nbsp; &nbsp; &nbsp; &nbsp; public void Paint(Graphics graphics)&nbsp; &nbsp; &nbsp; &nbsp; {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; graphics.FillRectangle(Brush, Rectangle);&nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; }这是它在表单中的使用方式:&nbsp; &nbsp; private void button2_Click(object sender, EventArgs e)&nbsp; &nbsp; {&nbsp; &nbsp; &nbsp; &nbsp; // define the displayer class&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; var displayer = new LedDisplayer(panel1);&nbsp; &nbsp; &nbsp; &nbsp; // define the array to initilize the displayer&nbsp; &nbsp; &nbsp; &nbsp; var display = new bool[,]&nbsp; &nbsp; &nbsp; &nbsp; {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; {true, false, false, true },&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; {false, true, false, false },&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; {false, false, true, false },&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; {true, false, false, false }&nbsp; &nbsp; &nbsp; &nbsp; };&nbsp; &nbsp; &nbsp; &nbsp; // and finally&nbsp; &nbsp; &nbsp; &nbsp; displayer.Initialize(display);&nbsp; &nbsp; }
打开App,查看更多内容
随时随地看视频慕课网APP