【问题标题】:Controlling a C# Winforms GUI with IronPython使用 IronPython 控制 C# Winforms GUI
【发布时间】:2010-08-04 03:23:26
【问题描述】:

所以我使用 C# 在 Visual Studio 中制作了一个 Winforms GUI,但是对于我正在处理的项目,我希望大部分代码都用 Python 编写。我希望用python(为了可移植性)编写“引擎”,然后让应用程序接口成为我可以换掉的东西。

我将 C# 项目编译为 .dll,并且能够将类导入 IronPython 脚本并正常启动 GUI。

问题是运行 GUI 会停止 Python 脚本的执行,除非我将它放入单独的线程中。但是,如果我将 GUI 放入一个单独的线程并尝试使用原始 python 线程来更改状态信息,我会收到一个异常,即从与创建控件不同的线程修改控件。

有什么好的方法可以与 GUI 线程进行通信或完成我想要做的事情吗?

GUI的C#驱动:

public class Program
{
    private static MainWindow window;

    [STAThread]
    static void Main()
    {
        Program.RunGUI();
    }

    public static void RunGUI()
    {
        Application.EnableVisualStyles();
        Application.SetCompatibleTextRenderingDefault(false);

        window = new MainWindow();
        Application.Run(window);
    }

    public static void SetState(GameState state)
    {
        window.State = state;
    }
}

还有python脚本:

import clr
clr.AddReferenceToFile("TG.Model.dll")
clr.AddReferenceToFile("TG.UI.dll")
from TG.Model import GameState
from TG.UI import Program
import thread
import time


def main():
    print "Hello!"
    state = GameState()
    print state.CharacterName
    print dir(Program)
    thread.start_new_thread(Program.RunGUI, ())
    #Program.RunGUI()
    time.sleep(2)
    Program.SetState(state)
    raw_input()


if __name__ == "__main__":
    main()

【问题讨论】:

    标签: c# python winforms ironpython


    【解决方案1】:

    将调用 Program.RunGUI() 之后的所有内容放入事件处理程序中。

    C#:

    public static void RunGUI(EventHandler onLoad)
    {   
        ...
    
        window = new MainWindow();
        window.Load += onLoad;
        Application.Run(window);
        window.Load -= onLoad; //removes handler in case RunGUI() is called again
    }
    

    Python:

    def onload(sender, args):
        time.sleep(2)
        Program.SetState(state)
        raw_input()  
    
    def main():
        ...
        Program.RunGUI(onload)
    

    【讨论】:

    • 这个解决方案看起来正是我想要的,但是当我尝试这样做时,onload() 函数中的代码没有运行。例如,如果我只是在其中放了一条打印语句,那么在 GUI 启动后什么都不会打印出来。任何想法为什么?感谢您的帮助!
    • 我不知道为什么。尝试从 python 实例化 MainWindow 类并直接添加事件处理程序——这在过去对我有用。
    • 你也可以闯入C#代码,看看事件处理程序是否确实注册了。
    • 啊,想通了 - onload 函数需要有事件处理程序的参数。再次感谢!
    • 酷。我更新了答案中的代码以包含参数。
    【解决方案2】:

    控件具有线程亲和性,并且只能由创建它们的线程访问。 有一个 BackgroundWorker 对象可以很好地处理线程之间的数据传递。

    【讨论】:

      【解决方案3】:

      如果你想在GUI线程之外的线程中修改GUI,你必须使用Invoke方法。

      【讨论】:

        猜你喜欢
        • 2012-12-30
        • 1970-01-01
        • 2019-03-18
        • 2013-05-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2021-07-06
        • 1970-01-01
        相关资源
        最近更新 更多