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

跨WinForm同步LED状态问题:静态变量方案失效求助

WinForm跨窗体LED状态同步问题解决方案

我看了你的代码,问题主要出在两个地方:Form2根本没读取静态类Led的状态,而且即使静态变量变化了,Form2也不会自动触发重绘更新LED。咱们一步步来修复:

问题分析

  1. Form2的OnPaint方法里用的是自己的私有字段isGreen,完全没用到你定义的Led.isGreen静态变量,这就导致Form1的状态变化根本传不过来。
  2. 就算你改成读取Led.isGreen,Form2也不会主动知道变量变化,除非强制触发重绘。

修复步骤

1. 升级静态Led类,添加状态变化事件

我们给静态类加一个事件,当isGreen变化时通知订阅者,这样Form2就能及时收到状态更新:

public static class Led {
    private static bool _isGreen;
    // 定义状态变化事件
    public static event Action<bool> IsGreenChanged;

    public static bool IsGreen {
        get => _isGreen;
        set {
            if (_isGreen != value) {
                _isGreen = value;
                // 触发事件,通知所有订阅者
                IsGreenChanged?.Invoke(value);
            }
        }
    }
}

2. 修正Form1的状态设置逻辑

原来Form1里直接给字段赋值,现在改成用属性,这样才会触发事件:

public class Form1 : Form {
    // ... 其他代码不变 ...
    protected override void OnPaint(PaintEventArgs args) {
        base.OnPaint(args);
        try {
            Nuitrack.Update(_skeletonTracker);
        } catch (LicenseNotAcquiredException exception) {
            Console.WriteLine("LicenseNotAcquired exception. Exception: ", exception);
            throw exception;
        } catch (Exception exception) {
            Console.WriteLine("Nuitrack update failed. Exception: ", exception);
        }
        args.Graphics.DrawImage(_bitmap.Bitmap, new Point(0, 0));
        Pen blackPen = new Pen(Color.Black, 5);
        args.Graphics.DrawEllipse(blackPen, 565, 403, 50, 50);
        
        // 先默认设为红色
        args.Graphics.FillEllipse(Brushes.Red, 565, 403, 50, 50);
        Led.IsGreen = false;

        if (_skeletonData != null && _skeletonData.Skeletons.Length > 0) {
            // 检测到骨骼,设为绿色
            args.Graphics.FillEllipse(Brushes.Green, 565, 403, 50, 50);
            Led.IsGreen = true;
        }
    }
}

这里还优化了判断逻辑:只有当骨骼数组不为空且有元素时才设为绿色,避免遍历空数组的冗余操作。

3. 让Form2订阅状态变化并更新LED

在Form2的构造函数里订阅Led.IsGreenChanged事件,并且修正OnPaint方法读取静态类的状态,同时处理线程安全(因为Nuitrack的更新可能在非UI线程):

public class Form2 : Form {
    // ... 其他代码不变 ...
    public Form2() { // 注意你原来的构造函数写的是FormPrincipale,应该改成Form2
        InitializeComponent();
        // 订阅LED状态变化事件
        Led.IsGreenChanged += OnLedStateChanged;
    }

    private void OnLedStateChanged(bool isGreen) {
        // WinForm控件必须在UI线程更新,所以检查是否需要Invoke
        if (InvokeRequired) {
            Invoke(new Action<bool>(OnLedStateChanged), isGreen);
            return;
        }
        // 触发重绘
        Invalidate();
    }

    protected override void OnPaint(PaintEventArgs e) {
        base.OnPaint(e);
        Pen blackPen = new Pen(Color.Black, 5);
        e.Graphics.DrawEllipse(blackPen, 615, 513, 40, 40);
        
        // 直接读取静态类的状态来绘制LED
        if (Led.IsGreen) {
            e.Graphics.FillEllipse(Brushes.Green, 615, 513, 40, 40);
        } else {
            e.Graphics.FillEllipse(Brushes.Red, 615, 513, 40, 40);
        }
    }

    // 记得在Dispose里取消订阅,避免内存泄漏
    protected override void Dispose(bool disposing) {
        if (disposing) {
            Led.IsGreenChanged -= OnLedStateChanged;
            components?.Dispose();
        }
        base.Dispose(disposing);
    }
}

另外注意你原来的Form2构造函数名称写错了,应该是public Form2()而不是FormPrincipale,这会导致窗体无法正常初始化,这个小问题也要修正。

为什么原来的方法不生效?

  • 你在Form2的OnPaint里用的是自己的isGreen字段,和静态类Led完全无关,所以Form1的状态变化根本不会影响到它。
  • 就算你改成读取Led.isGreen,Form2的OnPaint只会在窗体初始化、大小变化等默认触发重绘的场景下执行,不会因为静态变量变化自动刷新,所以需要通过事件触发Invalidate()来强制重绘。

这样修改后,Form2的LED就会和Form1的LED同步,检测到骨骼时一起变绿,未检测到时变回红色啦。

内容的提问来源于stack exchange,提问作者guido pastore

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.12 03:58:54