Controlling a C# Winforms GUI with IronPython
因此,我使用C#在Visual Studio中制作了Winforms GUI,但是对于我正在从事的项目,我希望大多数代码都用Python编写。我希望用python编写"引擎"(出于可移植性),然后使应用程序接口成为我可以交换的东西。
我将C#项目编译为.dll,并能够将这些类导入IronPython脚本中并正常启动GUI。
问题在于,除非我将其放入单独的线程中,否则运行GUI会停止执行Python脚本。但是,如果我将GUI放在一个单独的线程中,并尝试使用原始的python线程来更改状态信息,则会收到关于从与创建它的线程不同的线程修改控件的异常。
是否有任何与GUI线程通信的好方法或完成我试图做的事情的方法?
GUI的C#驱动程序:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 | 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脚本:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 | 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#:
1 2 3 4 5 6 7 8 9 | 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:
1 2 3 4 5 6 7 8 | def onload(sender, args): time.sleep(2) Program.SetState(state) raw_input() def main(): ... Program.RunGUI(onload) |
控件具有线程关联性,只能由创建它们的线程访问。
有一个BackgroundWorker对象可以很好地处理线程之间的数据传递。
如果要从GUI线程以外的线程中修改GUI,则必须使用Invoke方法。