在c#中制作可滚动的“图形”(可视化数据)

时间:2014-05-19 11:32:20

标签: c# scroll graph visualize

我试图想象一下我在C#表单中的一些数据。我一直在考虑几种可以做到这一点的方法,但无法弄清楚C#中最好的方法。

首先,让我展示一下我在油漆中所做的一个例子。

example http://www.interstyles.nl/example.png

我认为有些方法可以做到:

  1. 绘制一张包含所有数据的巨幅图片,然后滚动图片中的图片。这不是很好,因为数据可以变得非常宽。通常情况下,我希望数据的宽度大约为36000像素,因此这将是一幅巨大的图片!因此编程很容易,但需要大量的记忆。

  2. 与一个相同,但每行数据的单独图片只有1个像素的高,当我在屏幕上显示时,将其展开。更难编程,但节省了大量内存。还可以更轻松地对数据进行排序并打开/关闭行。简而言之,屏幕会被几张图片叠加在一起。

  3. 根据滚动条的位置,仅绘制表单大小的图片中的可见数据。更难编程,我想知道这是否足够快?

  4. c#中还有图形功能,但我找不到如何做这样的事情。

  5. 我还不了解其他一些图书馆。

  6. 当我将鼠标指针悬停在特定事件上时,我也希望获得有关特定事件的信息,这在选项1,2和3中很难实现,或者至少需要花费一些编程工作。

    建议

2 个答案:

答案 0 :(得分:0)

绘制所有可见点(您提到基于滚动条值获取视口并且宽度不是问题)。您无需进行太多优化,只需找到minTimemaxTime并继续执行所有积分。我怀疑它是否真的需要,因为试图绘制无形像素将不会绘制任何内容并且通过数组非常快,绘制几个像素将花费更多。

确保您启用了双缓冲:

[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听起来像是错误的方法:内部图像位图仍然具有完整的大小,即使你是从小块创建的,所以这里没有任何东西,更有可能丢失。

您可能希望选择像Format16bppRgb555Format16bppRgb565这样的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 ..