C# 基于侦听器类实现在运行时更改的Windows窗体

C# 基于侦听器类实现在运行时更改的Windows窗体,c#,winforms,leap-motion,C#,Winforms,Leap Motion,我目前正在为Leap Motion设备设计GUI(尽管我的问题可能会出现在任何类型的侦听器设备上) 我正在Windows窗体中运行应用程序,代码如下: public partial class FormRecord : Form { public FormRecord() { InitializeComponent(); } public void UpdateGUI(Frame frame) { //get informat

我目前正在为Leap Motion设备设计GUI(尽管我的问题可能会出现在任何类型的侦听器设备上)

我正在Windows窗体中运行应用程序,代码如下:

public partial class FormRecord : Form
{

    public FormRecord()
    {
        InitializeComponent();
    }

    public void UpdateGUI(Frame frame)
    {
     //get information from captured frame 
     //update the GUI (specifically labels)
     customLabel0.Text = someValueFromFrame.ToString();
    }
//该方法代码由Leap Motion在其网站上提供

    public static void RunMain() 
    {

        // Create a sample listener and controller
        SampleListener listener = new SampleListener();

        Controller controller = new Controller(); 
          //Controller is included in Leap.dll (from SDK) and is an instance of controller

        // Have the sample listener receive events from the controller
        controller.AddListener(listener);

        Console.WriteLine("Press Enter to quit...");
        Console.ReadLine();



        // Remove the sample listener when done
        controller.RemoveListener(listener);
        controller.Dispose();
    }
//该类也在Leap Motion SDK中提供

    class SampleListener : Listener
    {
    private Object thisLock = new Object();

        private void SafeWriteLine(String line)
        {
            lock (thisLock)
            {

                Console.WriteLine(line);
            }
        }

        public override void OnInit(Controller controller)
        {

            SafeWriteLine("Initialized");
        }

        public override void OnConnect(Controller controller)
        {

            SafeWriteLine("Connected");

        }

        public override void OnDisconnect(Controller controller)
        {

            //Note: not dispatched when running in a debugger.
            SafeWriteLine("Disconnected");
        }

        public override void OnExit(Controller controller)
        {

            SafeWriteLine("Exited");
        }

        public override void OnFrame(Controller controller) //
        //public void OnFrame(Controller controller)
        {

            SafeWriteLine("Framed");
            //Do something useful with the captured frame

            // get the current frame
            Frame frame = controller.Frame();

            /* This is where my problem occurs */
           // attempt to use information from this form and call UpdateGUI(Frame frame)

        }
      }    
}
基本上,这个问题是由于两个类在静态和非静态性质上的差异而产生的。例如,我的应用程序(Windows窗体)是非静态的,因为它是一个窗体,您必须能够自然地创建多个实例。然而,这就是为什么我不能简单地称之为:

Form aForm = new Form();
aForm.UpdateGUI();
^^这将创建一个新的表单。我希望能够在原始表单上使用UpdateGUI()方法

我也试过了

  guiForm = ActiveForm;
然后从那里给标签打电话

 ActiveForm.customlbl0.Text = valueToDisplay;
更一般地说,我尝试根据从侦听器接收的数据更新Windows窗体。这给我带来了麻烦,因为我不得不在静态和非静态成员之间挣扎。我将使它成为一个类,但是我需要为这两个组件实现表单和侦听器。如何使用侦听器中的实时数据更新显示


编辑:监听器是SDK文件“LeapCSharp.Net4.0dll”中的一个实现。

我会让SampleListener的构造函数获取表单类的一个实例。创建侦听器时,传入对表单的引用并将其存储在私有字段中。这样,您就可以从侦听器内部对其调用方法


另一个选项是让SampleListener类为每个事件引发事件。然后,您可以从表单内部钩住事件。

类似于:

public partial class FormRecord : Form
{
    Controller controller;

    public FormRecord()
    {
        InitializeComponent();
        controller = new Controller();
    }

    public void UpdateGUI()
    {
         Frame frame = controller.frame();

        //get information from captured frame 
        //update the GUI (specifically labels)
        customLabel0.Text = someValueFromFrame.ToString();
    }

如果使用侦听器,请注意每个侦听器回调都是在其自己的线程上调用的。通常不能从主线程以外的任何线程更新GUI框架(如Windows窗体等)直接访问的对象。(不过,我不知道在Windows窗体中进行跨线程通信的最佳方法。)

我会选择事件,因此
SampleListener
不依赖
Form
类。您有没有可能收集一些代码来帮我解决问题?我不太确定如何实现这些解决方案。侦听器无法更新表单,因为它的回调是在非GUI线程上调用的。您必须将事件/委托用于此方法。我添加了一个将代理用于Leap Motion文档的示例:成功了!我的印象是,它必须使用一个倾听者,但事实并非如此。我对这段代码的唯一更正是,从技术上讲,按照您提出的解决方案的方式,使用第二种方法更有意义,如下所示:
public void UpdateGUI(Controller)
,因为您将在下一行重新定义帧,覆盖引入的内容。侦听器只是获取帧的一种方法,而且由于线程问题,通常不是最直接的方法。另外,我在修改现有代码(现在已编辑)时忽略了框架参数。您也不需要传入控制器对象,因为它是一个实例属性(除非调用UpdateGUI()的对象拥有控制器实例而不是FormRecord类)。。