我试图想象一下我在C#表单中的一些数据。我一直在考虑几种可以做到这一点的方法,但无法弄清楚C#中最好的方法。
首先,让我展示一下我在油漆中所做的一个例子。
example http://www.interstyles.nl/example.png
我认为有些方法可以做到:
绘制一张包含所有数据的巨幅图片,然后滚动图片中的图片。这不是很好,因为数据可以变得非常宽。通常情况下,我希望数据的宽度大约为36000像素,因此这将是一幅巨大的图片!因此编程很容易,但需要大量的记忆。
与一个相同,但每行数据的单独图片只有1个像素的高,当我在屏幕上显示时,将其展开。更难编程,但节省了大量内存。还可以更轻松地对数据进行排序并打开/关闭行。简而言之,屏幕会被几张图片叠加在一起。
根据滚动条的位置,仅绘制表单大小的图片中的可见数据。更难编程,我想知道这是否足够快?
c#中还有图形功能,但我找不到如何做这样的事情。
我还不了解其他一些图书馆。
当我将鼠标指针悬停在特定事件上时,我也希望获得有关特定事件的信息,这在选项1,2和3中很难实现,或者至少需要花费一些编程工作。
建议
答案 0 :(得分:0)
绘制所有可见点(您提到基于滚动条值获取视口并且宽度不是问题)。您无需进行太多优化,只需找到minTime
,maxTime
并继续执行所有积分。我怀疑它是否真的需要,因为试图绘制无形像素将不会绘制任何内容并且通过数组非常快,绘制几个像素将花费更多。
确保您启用了双缓冲:
[System.ComponentModel.DesignerCategory("Code")]
public class MyGraph : PictureBox
{
public MyGraph()
{
SetStyle(ControlStyles.ResizeRedraw | ControlStyles.OptimizedDoubleBuffer | ControlStyles.UserPaint | ControlStyles.AllPaintingInWmPaint, true);
}
...
}
如果您确实需要优化某些内容(例如,如果您在用户移动鼠标时绘制一些信息数据),那么您可以使用缓存绘制到位图中然后只是bitblt(DrawImage
)位图。请参阅this回答或从位图搜索图形。当缓存的数据变得无效时(滚动,调整大小等),您将不得不处理这种情况。
另一种可能性是优化更新(例如,如果您的绘制数据定期更新)。为此,您需要在MyGraph
中提供一个方法来通知底层数据发生了什么变化,确定缓存何时变为无效,或者通过向其中绘制更改来更新缓存的位图。
还有一个,真正的开销,但优化:你可以将数据保存在尽可能接近位图的位置。这样在MyGraph
中绘制函数只会绘制位图(这很快并且将支持客户端视口)。这样更新就像更改该像素并调用Invalidate()
一样简单。
答案 1 :(得分:0)
我讨厌的一件事是滚动条对我来说是。所以我同意Siantr:选择选项1,创建完整尺寸,不要在实际出现问题之前进行优化。
关于SO的最常被引用的评论可能是Knuth's:过早优化是所有邪恶的根源
特别是选项2听起来像是错误的方法:内部图像位图仍然具有完整的大小,即使你是从小块创建的,所以这里没有任何东西,更有可能丢失。
您可能希望选择像Format16bppRgb555
或Format16bppRgb565
这样的PixelFormat来节省一些内存;但我不确定这是否会对记忆产生影响。它肯定会在写入文件时,但Winforms内部有神秘的方式..
要显示事件详细信息,假设您有一个工具提示控件toolTip1
,您可以像这样使用光标坐标:
private void pictureBox1_MouseHover(object sender, EventArgs e)
{
Point p = pictureBox1.PointToClient(Cursor.Position);
string msg = String.Format("row {0} column {1}", p.Y , p.X );
toolTip1.SetToolTip(pictureBox1, msg);
}
PointToClient()
方法足够友好,可以为您计算滚动位置。
当然,你必须将坐标映射到你的活动.. 要首先获取滚动条,您必须使用this old trick ..