日期:2014-05-18  浏览次数:20937 次

C#Panel画10万个图形
我需要在Panel里画10万个长方形,每个长方形用线隔开,Panel长度固定,超出会出现滚动条,我试了2种方法,第一创建1000个Panel每个Panel里放1000个小Panel,但是出现异常win32Exception,第二我也创建了1000个Panel,每个Panel里放一个PictureBox,然后画图片,用Bitmap画出1000个长方形,然后将图片放入picture,但是我的长方形宽度会根据我需要变大,所以也出现异常,在appliction.run里出现argumentException,可能是图片过大吧,大家有没有什么好的方法啊,求教。。

------解决方案--------------------
UI Virtualization
最近正好在看这个,只显示你看得到的部分
http://nonocast.cn/?s=UI+Virtualization
------解决方案--------------------
探讨

我的电脑确实不行,1G内存,基本很容易挂的,如果在一个PANEL里画的话,写在PAINT事件里吗?我的图是需要更新的,我觉得会消耗更大。10万个用滚动条显示,我的PANEL宽度给固定了,控件的话貌似确实不行。C#控件初始化个数有限制吧。

------解决方案--------------------
按你的意思做了一个演示程序,10万个方块,效果图如下:


程序做得比较简单,所有方块的大小都是一样的,其中的代码楼主你慢慢研究吧。代码如下,要能正常运行,请按上图在窗体上放置2个NumericUpDown控件用于输入列数和行数,另外再放一个Button,并把它的Click事件绑定到button1_Click方法上就可以了。

C# code

    public partial class Form7 : Form
    {
        // 定义方块的宽度、高度和间距。
        const int BLOCK_WIDTH = 80, BLOCK_HEIGHT = 30, BLOCK_SPACE = 2;

        Block[,] _blocks;

        public Form7()
        {
            InitializeComponent();
        }

        protected override void OnLoad(EventArgs e)
        {
            base.OnLoad(e);

            Initialize();
        }

        private void panel1_Paint(object sender, PaintEventArgs e)
        {
            if (_blocks != null)
            {
                Rectangle rect = e.ClipRectangle;
                Point offset = panel1.AutoScrollPosition;
                
                // 根据滚动条的位置进行调整
                rect.Offset(-offset.X, -offset.Y);

                // 计算出哪些方块需要重绘
                int x0 = rect.Left / (BLOCK_WIDTH + BLOCK_SPACE);
                int x1 = (rect.Right - 1) / (BLOCK_WIDTH + BLOCK_SPACE);
                int y0 = rect.Top / (BLOCK_HEIGHT + BLOCK_SPACE);
                int y1 = (rect.Bottom - 1) / (BLOCK_HEIGHT + BLOCK_SPACE);

                for (int y = y0; y <= y1; y++)
                {
                    for (int x = x0; x <= x1; x++)
                    {
                        Rectangle rectBlock = new Rectangle(
                            x * (BLOCK_WIDTH + BLOCK_SPACE) + BLOCK_SPACE,
                            y * (BLOCK_HEIGHT + BLOCK_SPACE) + BLOCK_SPACE,
                            BLOCK_WIDTH, BLOCK_HEIGHT);

                        rectBlock.Offset(offset);

                        // 绘制方块
                        RenderBlock(_blocks[y, x], rectBlock, e);
                    }
                }
            }
        }

        private void RenderBlock(Block block, Rectangle rect, PaintEventArgs e)
        {
            Color backColor = block.Color;
            Color foreColor = Color.FromArgb(
                255 - backColor.R,
                255 - backColor.G,
                255 - backColor.B);

            Brush br;

            // 绘制渐变底色
            br = new System.Drawing.Drawing2D.LinearGradientBrush(
                rect, Color.White, backColor, 45f);
            e.Graphics.FillRectangle(br, rect);
            br.Dispose();

            // 绘制文字
            br = new SolidBrush(foreColor);
            TextRenderer.DrawText(e.Graphics,
                string.Format("x={0},y={1}", block.X + 1, block.Y + 1),
                panel1.Font,
                rect, foreColor);
            br.Dispose();

            // 绘制边框
            Pen pen = new Pen(backColor);
            e.Graphics.DrawRectangle(pen,
                rect.X, rect.Y, rect.Width - 1, rect.Height - 1);
            pen.Dispose();
            
        }

        class Block
        {
            public int X { get; set; }

            public int Y { get; set; }

            public Color Color { get; set; }


        }

        private void button1_Click(object sender, EventArgs e)
        {
            Initialize();
        }

        private void Initialize()
        {