在C# Visual Studio中使用Graphics.DrawLine绘制线条时出错
解决你的C# WinForm绘图代码问题
我帮你排查了代码里的几个关键问题,这几个点正是导致报错和程序异常的根源:
核心问题拆解
- 错误释放系统管理的Graphics对象:你在循环里调用了
l.Dispose();,但e.Graphics是WinForm框架提供并负责回收的资源,手动Dispose会直接导致后续绘图操作失效,抛出异常。 - 浮点数精度引发的无限循环:
angle == 360这个判断几乎永远不会成立——因为浮点数的精度限制,每次累加0.001F后,angle很难刚好等于360,循环会一直占用UI线程,直接卡死界面。 - 角度与弧度概念混淆:
Math.Sin和Math.Cos的参数是弧度而非角度!你传入0-360的角度值,绘制出来的图形完全不符合预期,逻辑上应该用弧度的2π(对应360度)作为循环终止条件。 - GDI+资源泄漏:
Pen p没有用using语句包裹,长期运行会造成资源浪费。 - UI线程阻塞:在Paint事件里写无限循环会彻底卡住界面,因为Paint事件本身就在UI线程执行,循环会耗尽线程资源。
修正后的静态绘图代码
private void Form1_Paint(object sender, PaintEventArgs e) { // 使用using自动释放Pen资源,避免GDI+泄漏 using (Pen p = new Pen(Color.Black, 1)) { Graphics g = e.Graphics; float len = 100; PointF ori = new PointF(Width / 2, 0); // 弧度的2π对应360度,作为循环终止条件 float totalRadians = (float)(Math.PI * 2); float angleStep = 0.01F; // 适当加大步长,减少不必要的绘图次数 // 用for循环替代while,避免无限循环风险 for (float angle = 0; angle <= totalRadians; angle += angleStep) { float bobX = ori.X + len * (float)Math.Sin(angle); float bobY = ori.Y + len * (float)Math.Cos(angle); PointF bob = new PointF(bobX, bobY); // 修正椭圆位置,让圆心刚好落在bob点上 g.DrawLine(p, ori, bob); g.DrawEllipse(p, bob.X - 15, bob.Y - 15, 30, 30); } } }
如果你需要动态摆锤动画
上面的代码是静态绘制完整摆线,如果要做动态摆动效果,别在Paint事件里写循环,改用Timer控件驱动重绘,避免阻塞UI线程:
private float _currentAngle = 0; private readonly float _angleStep = 0.05F; private readonly float _pendulumLength = 100; private void Form1_Load(object sender, EventArgs e) { Timer animationTimer = new Timer(); animationTimer.Interval = 16; // 约60帧/秒,保证动画流畅 animationTimer.Tick += AnimationTimer_Tick; animationTimer.Start(); } private void AnimationTimer_Tick(object sender, EventArgs e) { _currentAngle += _angleStep; // 重置角度,避免数值过大 if (_currentAngle > Math.PI * 2) { _currentAngle = 0; } Invalidate(); // 触发Paint事件重绘界面 } private void Form1_Paint(object sender, PaintEventArgs e) { using (Pen p = new Pen(Color.Black, 1)) { Graphics g = e.Graphics; PointF ori = new PointF(Width / 2, 0); float bobX = ori.X + _pendulumLength * (float)Math.Sin(_currentAngle); float bobY = ori.Y + _pendulumLength * (float)Math.Cos(_currentAngle); PointF bob = new PointF(bobX, bobY); g.DrawLine(p, ori, bob); g.DrawEllipse(p, bob.X - 15, bob.Y - 15, 30, 30); } }
内容的提问来源于stack exchange,提问作者Wow Facts Wrong
相关产品推荐
相关产品推荐

