PythonNet 是一个 Python 包,允许在 Python 中与 .NET 运行时环境无缝集成,兼容 Python 2.7 以及 Python 3.5-3.7 。本文以 Python 调用 .NET System.Windows.Forms
为例,演示 PythonNet 的使用方法。
PythonNet 支持 pip 方式安装:
pip install pythonnet
用一个简单的示例,演示 Python 调用 .NET 的方法。首先我们使用 Visual Studio 2019 创建一个 WinForm App 项目:
项目只有一个 Form: Form1,Form1 设计时界面如下:
- Form1.cs: 开发者的代码放在 Form1.cs 文件中
- Form1.Desiner.cs : WinForm 设计器自动生成的代码,不建议修改
设计器的生成的界面代码都在 Form1.Desiner.cs
文件中。打开这个文件,主要关注 InitializeComponent
这个 private 方法。界面的主要代码都在这个方法中。
private void InitializeComponent() {
this.textBox1 = new System.Windows.Forms.TextBox();
this.button1 = new System.Windows.Forms.Button();
this.SuspendLayout();
//
// textBox1
//
this.textBox1.Location = new System.Drawing.Point(156, 48);
this.textBox1.Name = "textBox1";
this.textBox1.Size = new System.Drawing.Size(290, 21);
this.textBox1.TabIndex = 0;
this.textBox1.Text = "Helllo World";
//
// button1
//
this.button1.Location = new System.Drawing.Point(156, 140);
this.button1.Name = "button1";
this.button1.Size = new System.Drawing.Size(147, 23);
this.button1.TabIndex = 1;
this.button1.Text = "Click Me";
this.button1.UseVisualStyleBackColor = true;
this.button1.Click += new System.EventHandler(this.Button1_Click);
//
// Form1
//
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 12F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.ClientSize = new System.Drawing.Size(709, 354);
this.Controls.Add(this.button1);
this.Controls.Add(this.textBox1);
this.Name = "Form1";
this.Text = "Form1";
this.ResumeLayout(false);
this.PerformLayout();
}
这段代码主要是创建一个 TextBox 控件,一个 Button 控件,设置属性,然后加载到 Form 中。我们将代码移植到 Python 中。
PythonNet 允许 CLR 像 Python 自身的 package 一样使用,其他的模块和 package 则需要导入,就像下面的语句:
import clr
clr.AddReference("System.Windows.Forms")
from System.Windows.Forms import Form
然后,编写一个 HelloForm 类,从 WinForm 继承:
from System.Drawing import Size, Point
import System.Windows.Forms as WinForms
class HelloForm(WinForms.Form):
def __init__(self):
self.textBox1 = WinForms.TextBox()
self.button1 = WinForms.Button()
self.SuspendLayout()
# textBox1
self.textBox1.Location = Point(156, 48)
self.textBox1.Name = "textBox1"
self.textBox1.Size = Size(290, 21)
self.textBox1.TabIndex = 0
self.textBox1.Text = "Helllo World"
# button1
self.button1.Location = Point(156, 140)
self.button1.Name = "button1"
self.button1.Size = Size(147, 23)
self.button1.TabIndex = 1
self.button1.Text = "Click Me"
self.button1.UseVisualStyleBackColor = True
self.button1.Click += self.button_Click
# Form1
self.AutoScaleMode = WinForms.AutoScaleMode.Font
self.ClientSize = Size(709, 354)
self.Controls.Add(self.button1)
self.Controls.Add(self.textBox1)
self.Name = "Form1"
self.Text = "Form1"
self.ResumeLayout(False)
self.PerformLayout()
def button_Click(self, sender, args):
"""Button click event handler"""
WinForms.MessageBox.Show("Hello, there.")
将 __init__
方法与 InitComponent
方法比较,可以看出,主要的区别在于不同语言的语法,而方法、方法的调用则基本类似。更精妙的是,Python 以类似的语法实现了 .NET 的事件:
this.button1.Click += new System.EventHandler(this.Button1_Click)
self.button1.Click += self.button_Click
再比较下 button click 事件的代码:
private void Button1_Click(object sender, EventArgs e) {
MessageBox.Show("Hello, there!");
}
def button_Click(self, sender, args):
WinForms.MessageBox.Show("Hello, there.")
WinForm 的启动代码在 program.cs
文件中:
def main():
form = HelloForm()
app = WinForms.Application
app.Run(form)
最后给出 Python 的完整代码:
import clr
clr.AddReference("System.Windows.Forms")
from System.Drawing import Size, Point
import System.Windows.Forms as WinForms
class HelloForm(WinForms.Form):
def __init__(self):
self.textBox1 = WinForms.TextBox()
self.button1 = WinForms.Button()
self.SuspendLayout()
# textBox1
self.textBox1.Location = Point(156, 48)
self.textBox1.Name = "textBox1"
self.textBox1.Size = Size(290, 21)
self.textBox1.TabIndex = 0
self.textBox1.Text = "Helllo World"
# button1
self.button1.Location = Point(156, 140)
self.button1.Name = "button1"
self.button1.Size = Size(147, 23)
self.button1.TabIndex = 1
self.button1.Text = "Click Me"
self.button1.UseVisualStyleBackColor = True
self.button1.Click += self.button_Click
# Form1
self.AutoScaleMode = WinForms.AutoScaleMode.Font
self.ClientSize = Size(709, 354)
self.Controls.Add(self.button1)
self.Controls.Add(self.textBox1)
self.Name = "Form1"
self.Text = "Form1"
self.ResumeLayout(False)
self.PerformLayout()
def button_Click(self, sender, args):
"""Button click event handler"""
print("Click")
WinForms.MessageBox.Show("Hello, there.")
def main():
form = HelloForm()
app = WinForms.Application
app.Run(form)
if __name__ == '__main__':
main()
github : pythonnet-winform-hello