在Winforms中绘制心电图

时间:2009-08-19 13:07:05

标签: c# winforms plot

我之前没有绘制winforms的经验,我希望以一种形式绘制ecg。或者让我说一个特定区域的一个正弦波或任何波函数,但我正在做的是e.c.g ..表格的其余部分将是带有按钮和标签的正常形式,

任何人都可以通过教程

:)

4 个答案:

答案 0 :(得分:2)

您没有多少选择,您可以编写自己的控件,处理数据并进行渲染。对于更复杂的图形,这可能有点复杂,但基础总是相同的,设置X和Y值范围,然后使用GDI从左到右绘制一条线,没什么花哨的。
对于更高级的功能,这可能会有点复杂,你可以使用一些图表控件,我读过this帖子或检查codeproject.com,我记得,我看到很少尝试写一些像样的图表控件,哪些是开源的,新文章可能会在WPF中编码,但你也应该找到更老的东西 编辑:
您可以找到一些有用的链接:Graph plotting lib that's main goal is to simulate ECG another graph plotting lib

答案 1 :(得分:1)

您需要创建自定义控件。

public class MyECGDrawer : Control{}

在其中,您覆盖OnPaint事件

protect override OnPaint(PaintEventArgs pe ){}

然后在绘画功能中,你按照你想要的方式绘制你的图形,让我们说sin(x)

// refresh background
pe.Graphics.FillRectangle( Brushes.White, 0, 0, Width, Height );
int prevX = -1, prevY = -1;
for(int x = 0; x < Width; x++ )
{
    if( prevX >= 0 )
    {
        pe.Graphics.DrawLine( Pens.Black, prevX, prevY, x, Math.sin(x) );
    }
    prevX = x;
    prevY = Math.sin(x);
}

要强制重绘ECG,请调用控件上的.Invalidate()函数。您应该能够从设计器中拖放窗体中的控件。

最后,该课程看起来像

公共类MyECGDrawer:Control {}

在其中,您覆盖OnPaint事件

public class MyECGDrawer : Control
{
protect override OnPaint(PaintEventArgs pe )
{
   // refresh background
    pe.Graphics.FillRectangle( Brushes.White, 0, 0, Width, Height );
    int prevX = -1, prevY = -1;
    for(int x = 0; x < Width; x++ )
    {
        if( prevX >= 0 )
            pe.Graphics.DrawLine( Pens.Black, prevX, prevY, x, Math.sin(x) );
        prevX = x;
        prevY = Math.sin(x);
    }
}
}

答案 2 :(得分:1)

我写了以下内容并对其进行了测试。它似乎做你想要的,但请注意,它只是简单地将sin(x)绘制在一个没有延迟的循环中 - 即sin(x)的绘图从左边缘流出来得如此之快,你很难看到它。但是,您可以在循环内的任何一条线上休息一下,然后用F5逐步完成循环,看看它的运行速度很慢 - 大概你的流式心电图数据只会以一定的速度到达,所以这不应该是你实施中的问题

在下文中,monitor是winforms表单上的PictureBox。其他一切都是本地的。

private void drawStream(){
  const int scaleX = 40;
  const int scaleY = 40;
  Point monitorTopLeft = new Point(0, 0);
  Point MonitorTopLeftMinus1 = new Point(-1, 0);

  int halfX = monitor.Width / 2;
  int halfY = monitor.Height / 2;
  Size size = new Size(halfX + 20, monitor.Height);

  Graphics g = monitor.CreateGraphics();
  g.TranslateTransform(halfX, halfY);
  g.ScaleTransform(scaleX, scaleY);
  g.Clear(Color.Black);
  g.ResetClip();

  float lastY = (float)Math.Sin(0);
  float y = lastY;
  Pen p = new Pen(Color.White, 0.01F);
  float stepX = 1F / scaleX;

  for (float x = 0; x < 10; x += stepX) {
    g.CopyFromScreen(monitor.PointToScreen(monitorTopLeft), MonitorTopLeftMinus1, size, CopyPixelOperation.SourceCopy);
    y = (float)Math.Sin(x);
    g.DrawLine(p, -stepX, lastY, 0, y);
    lastY = y;
  }
}

可能有用的其他一些信息:

  1. 图片框中的原点开始 在左上角。 TranslateTransform允许您 翻译(即移动)原点。 在这个例子中,我翻译了它 图片框宽度的一半 高度的一半。
  2. ScaleTransform更改了图片框的放大倍数 - 请注意,它甚至会放大用于在图片框上绘制的笔的宽度 - 这就是笔的宽度设置为0.01的原因。
  3. CopyFromScreen执行bitblt。它的源点是相对于屏幕的,目的地是相对于图片框而且要移动的矩形的大小忽略任何变换(比如我们添加的缩放和平移变换)。
  4. 请注意,X坐标在DrawLine的方法是-stepx和0所有的绘制基本上发生右y轴(即,X = 0),然后CopyFromScreen移动引出部向左侧以使其“流”关在左边。

答案 3 :(得分:0)

除非您将此作为学习经历,否则您可能需要考虑在此处查看免费的Microsoft Chart Controls for .NET。

http://www.microsoft.com/downloads/details.aspx?FamilyID=130f7986-bf49-4fe5-9ca8-910ae6ea442c&displaylang=en#QuickInfoContainer

话虽如此,如果你想自己动手,我会提供以下指导。

  1. 创建用户控件以封装绘图呈现,而不是直接在表单上呈现。
  2. 在您的控件中,公开属性以获取/设置您想要渲染的数据,并添加您想要控制渲染的任何其他属性(缩放,平移,颜色等)。
  3. 在您的控件中,要么覆盖OnPaint方法,要么为Paint事件创建事件处理程序。这些方法将传递一个PaintEventArgs对象,它包含一个Graphics对象作为属性。 Graphics对象的方法用于在需要绘制时将点,线等渲染到控件上。大多数绘图操作需要笔(轮廓/线条)或笔刷(填充区域)。您可以使用库存对象进行这些操作(例如Pens.Black或Brushes.Red),也可以创建自己的(参见文档)。如果您创建自己的对象,请确保在使用它们之后将其丢弃(例如,使用“using”语句或通过调用Dispose)。
  4. GDI +上有几本好书。如果你要深入,我建议你选择一个。