我以前没有在winforms中绘图的经验,我想以一种形式绘制心电图。或者让我们说一个特定区域的正弦波或任何波函数,但我正在做的是心电图。表单的其余部分将是带有按钮和标签的普通表单,
任何人都可以很好地完成教程吗
:)
您几乎没有选择,您可以编写自己的控件,它将处理数据并呈现它。对于更复杂的绘图,这可能有点复杂,但基本原理始终相同,设置 X 和 Y 值范围,然后使用 GDI 从左到右画一条线,没什么特别的。
由于这对于更高级的功能可能会有点复杂,您可以使用一些图表控件,我会阅读这篇文章或查看 codeproject.com,我记得,我看到很少有人尝试编写一些像样的图表控件,它们是开源的,新文章可能会在 WPF 中编码,但您也应该找到较旧的文章。
编辑:
您会发现一些有用的链接:Graph plotting lib 的主要目标是模拟 ECG或另一个绘图库
您需要创建一个自定义控件。
public class MyECGDrawer : Control{}
在其中,您覆盖 OnPaint 事件
protect override OnPaint(PaintEventArgs pe ){}
然后在paint函数中,按照你想要的方式绘制你的图形,比如说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);
}
要强制心电图重绘,请调用控件上的 .Invalidate() 函数。您应该能够从设计器中拖放表单中的控件。
最后,课程看起来像
公共类 MyECGDrawer:控制{}
在其中,您覆盖 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);
}
}
}
我写了以下内容并进行了测试。它似乎在做你想做的事,但请注意,它只是在没有延迟的循环中简单地绘制 sin(x) - 即 sin(x) 的图从左边缘流出的速度如此之快,以至于你几乎看不到它。但是,您可以在循环内的任何行上打断,然后使用 F5 单步执行循环以查看它是否运行缓慢 - 大概您的流式 ECG 数据只会以某个固定速度到达,因此这在您的实施中应该不是问题.
在下文中,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;
}
}
一些可能有用的附加信息:
除非您将此作为一种学习体验,否则您可能需要考虑查看此处提供的免费 Microsoft Chart Controls for .NET。
话虽如此,如果您想自己动手,我会提供以下指导方针。
有几本关于 GDI+ 的好书。如果您要深入,我建议您选择一个。