You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在2D CNC模拟器画布上绘制不干扰内容的工具定位光标?

实现不干扰画布的CNC模拟器光标方案

针对你的需求,推荐几个简单易上手、不会破坏原有图形的光标实现方法,都是适合编程新手的思路:

方法1:分层绘制(最推荐)

核心思路是把画布分成两层:

  • 底层:专门存放工具塑造的图形(静态或低频更新)
  • 上层:只用来绘制光标(高频更新)

每次更新时,只需要单独处理对应的层,不用动底层的图形:

  1. 先创建两个绘制载体(比如两个Bitmap,不同框架叫法可能不同):一个存工具画的图,一个存光标。
  2. 工具加工图形时,只在底层载体上操作。
  3. 光标移动时,先清空上层载体(用透明色),再在新位置绘制光标(比如十字线+坐标文本)。
  4. 最后把底层和上层叠加显示到屏幕上。

举个C# WinForms的代码示例(其他框架逻辑类似):

// 初始化两个Bitmap,假设画布尺寸是800x600
Bitmap background = new Bitmap(800, 600); // 存工具绘制的图形
Bitmap cursorLayer = new Bitmap(800, 600); // 存光标

// 工具绘图时,在background上操作
void DrawToolShape(int x, int y)
{
    using (Graphics g = Graphics.FromImage(background))
    {
        g.FillEllipse(Brushes.Blue, x-5, y-5, 10, 10); // 示例:画一个加工点
    }
}

// 更新光标位置
void UpdateCursor(int newX, int newY)
{
    using (Graphics g = Graphics.FromImage(cursorLayer))
    {
        g.Clear(Color.Transparent); // 清除旧光标
        // 画十字光标
        g.DrawLine(Pens.Red, newX, 0, newX, 600);
        g.DrawLine(Pens.Red, 0, newY, 800, newY);
        // 绘制坐标文本
        g.DrawString($"X: {newX}, Y: {newY}", new Font("Arial", 10), Brushes.Red, newX+5, newY+5);
    }
    // 把两层合并显示到画布控件
    using (Graphics g = canvasControl.CreateGraphics())
    {
        g.DrawImage(background, 0, 0);
        g.DrawImage(cursorLayer, 0, 0);
    }
}

这个方法逻辑清晰,不会破坏原有图形,速度也快,因为只需要更新光标层。

方法2:XOR绘图模式

利用图形API的XOR模式,绘制光标时会和原有像素做异或运算,再次绘制相同内容就能恢复原像素:

void DrawOrEraseCursor(Graphics g, int x, int y, bool erase)
{
    Pen xorPen = new Pen(Color.Red);
    xorPen.XorMode = true; // 开启XOR模式

    // 擦除旧光标就是用同样的Pen再画一次
    g.DrawLine(xorPen, x, 0, x, 600);
    g.DrawLine(xorPen, 0, y, 800, y);
    
    if (!erase)
    {
        // 非擦除状态下再绘制坐标文本
        g.DrawString($"X: {x}, Y: {y}", new Font("Arial",10), Brushes.Red, x+5, y+5);
    }
}

// 使用方式:移动光标前先擦除旧的,再画新的
DrawOrEraseCursor(g, oldX, oldY, erase: true);
DrawOrEraseCursor(g, newX, newY, erase: false);

注意:XOR模式下光标颜色可能会和背景色产生奇怪的混合,但好处是不用额外分层,代码量少。

方法3:绘制流程末尾加光标

如果你的模拟器是每一帧都重新绘制整个画面(比如有固定的刷新循环),那直接在所有图形绘制完成后,最后画光标即可:

void OnPaint(Graphics g)
{
    // 1. 清空画布
    g.Clear(Color.White);
    // 2. 绘制所有工具加工的图形
    DrawAllToolPaths(g);
    // 3. 最后绘制光标和坐标
    g.DrawLine(Pens.Red, currentX, 0, currentX, 600);
    g.DrawLine(Pens.Red, 0, currentY, 800, currentY);
    g.DrawString($"X: {currentX}, Y: {currentY}", new Font("Arial",10), Brushes.Red, currentX+5, currentY+5);
}

这个方法逻辑最简单,完全不用考虑像素保存恢复,适合有固定刷新逻辑的场景。

新手额外提示

  • 别再直接操作单个像素了,不仅慢还容易出各种边界、颜色保存的bug。
  • 之前透明Bitmap没成功,大概率是创建时没指定支持Alpha通道,比如C#里要选PixelFormat.Format32bppArgb格式的Bitmap。

内容的提问来源于stack exchange,提问作者Vojtjikjhh -4K-

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.23 01:30:11