C#Panel画10万个图形

wozuiaijiahui 2012-05-15 03:17:46
我需要在Panel里画10万个长方形,每个长方形用线隔开,Panel长度固定,超出会出现滚动条,我试了2种方法,第一创建1000个Panel每个Panel里放1000个小Panel,但是出现异常win32Exception,第二我也创建了1000个Panel,每个Panel里放一个PictureBox,然后画图片,用Bitmap画出1000个长方形,然后将图片放入picture,但是我的长方形宽度会根据我需要变大,所以也出现异常,在appliction.run里出现argumentException,可能是图片过大吧,大家有没有什么好的方法啊,求教。。
...全文
356 17 打赏 收藏 转发到动态 举报
写回复
用AI写文章
17 条回复
切换为时间正序
请发表友善的回复…
发表回复
cheng2005 2012-05-16
  • 打赏
  • 举报
回复
[Quote=引用 10 楼 的回复:]

我的电脑确实不行,1G内存,基本很容易挂的,如果在一个PANEL里画的话,写在PAINT事件里吗?我的图是需要更新的,我觉得会消耗更大。10万个用滚动条显示,我的PANEL宽度给固定了,控件的话貌似确实不行。C#控件初始化个数有限制吧。
[/Quote]
你应该考虑的是,真的有必要一下把这些东西都处理好放到UI里吗?
会有人一下子看10万张图??机器能承受的住,人能承受住吗?
主要把大问题分解啊,别傻傻地认为什么事情就是一口气憋出来的。
wozuiaijiahui 2012-05-16
  • 打赏
  • 举报
回复
我的电脑确实不行,1G内存,基本很容易挂的,如果在一个PANEL里画的话,写在PAINT事件里吗?我的图是需要更新的,我觉得会消耗更大。10万个用滚动条显示,我的PANEL宽度给固定了,控件的话貌似确实不行。C#控件初始化个数有限制吧。
wozuiaijiahui 2012-05-16
  • 打赏
  • 举报
回复
问题解决了,多谢effun,你的方法确实可以,还有感谢大家的意见,有时候进个死胡同真的很难出来,以后得多练练。结贴,分少,见谅。
effun 2012-05-16
  • 打赏
  • 举报
回复
[Quote=引用 15 楼 的回复:]

14楼那位朋友,我的程序是一行10万个矩形,不是多行,还有你的程序不会卡吗?我感觉一行放10个矩形,拖动滚动条会非常卡。
[/Quote]

卡不卡并不取决于一共有多少个矩形,而是取决于可见的矩形有几个。如果按你说的只有一行,那应该更不会卡,因为可见的矩形少了。
wozuiaijiahui 2012-05-16
  • 打赏
  • 举报
回复
5楼和11楼说的很有道理,我确实应该考虑用户看到的只有我PANEL大小里那么几个,不会一次看10万个,14楼那位朋友,我的程序是一行10万个矩形,不是多行,还有你的程序不会卡吗?我感觉一行放10个矩形,拖动滚动条会非常卡。
effun 2012-05-16
  • 打赏
  • 举报
回复
按你的意思做了一个演示程序,10万个方块,效果图如下:


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


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()
{
// 按界面控件指定的值初始化存储方块的二维数组
_blocks = CreateBlocks((int)numericUpDown1.Value, (int)numericUpDown2.Value);

// 根据方块的行列数和方块的大小,计算虚拟空间的大小,以此来为Panel产生滚动条。
Size size = new System.Drawing.Size(
_blocks.GetLength(1) * (BLOCK_WIDTH + BLOCK_SPACE),
_blocks.GetLength(0) * (BLOCK_HEIGHT + BLOCK_SPACE));

panel1.AutoScroll = true;
panel1.AutoScrollMinSize = size;

// 所有初始化工作完成后,通知Panel控件进行重绘。
panel1.Invalidate();
}

private Block[,] CreateBlocks(int columnCount, int rowCount)
{
Block[,] array = new Block[rowCount, columnCount];

Random rnd = new Random();

for (int y = 0; y < rowCount; y++)
{
for (int x = 0; x < columnCount; x++)
{
Block block = new Block();

block.X = x;
block.Y = y;
block.Color = Color.FromArgb(rnd.Next(256), rnd.Next(256), rnd.Next(256));

array[y, x] = block;
}
}

return array;

}
}
test2050 2012-05-16
  • 打赏
  • 举报
回复
你要支持计数。呵呵。每个容器代表图形的编号。如一屏第一行放了编号1..5个。最后一行放编号10..15
往下滚动时重画一屏第一行放了编号6..10个。最后一行放编号16..20
effun 2012-05-16
  • 打赏
  • 举报
回复
[Quote=引用 10 楼 的回复:]

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

不管你有几个图形,屏幕的大小总是有限制的吧,10万个图形不可能一次性全部显示到窗口里吧,需要画的只是可见部分的图形,可能只是几十个吧。
你说得不错,在Panel里画的话只需要在Paint事件里操作就可以了,至于更新也不是问题,只要在需要更新的时候调用Invalidate方法就可以强制重绘控件。
test2050 2012-05-15
  • 打赏
  • 举报
回复
乖乖,10万个怎么摆?
止境 2012-05-15
  • 打赏
  • 举报
回复
10万个。。。虽然没接触过,但我想知道这么画的画面板里能画的下么?
jontian 2012-05-15
  • 打赏
  • 举报
回复
用GDI+在一个panel中图就行,干嘛用那么多来画,不过画完不知要多长时间,我原来根据数据来画连线画过几W数点,好像比较慢
Conmajia 2012-05-15
  • 打赏
  • 举报
回复
微粒模式+视口

话说最近我也在研究这个
nonocast 2012-05-15
  • 打赏
  • 举报
回复
UI Virtualization
最近正好在看这个,只显示你看得到的部分
http://nonocast.cn/?s=UI+Virtualization
theillusion 2012-05-15
  • 打赏
  • 举报
回复
好家伙,10万个!还是用gdi+自己画吧,控件们肯定干不了这活

effun 2012-05-15
  • 打赏
  • 举报
回复
最现实的办法是在1个Panel里画
showjancn 2012-05-15
  • 打赏
  • 举报
回复
不宜如此。

参考一下“享元模式”
crackdung 2012-05-15
  • 打赏
  • 举报
回复
你電腦能承受?

110,538

社区成员

发帖
与我相关
我的任务
社区描述
.NET技术 C#
社区管理员
  • C#
  • Web++
  • by_封爱
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告

让您成为最强悍的C#开发者

试试用AI创作助手写篇文章吧