IronPython的飘亮之处大部分在于它的动态风格开发-- 通过添加功能元素,改变(modifying)运行着的应用(程序)。在Windows 应用中, 这通常要求 delegates 和 event 处理 (i.e., 向现有的form窗口添加按钮,然后对按钮添加按下的处理功能代码).
本tutorial 专注于在IronPython 中创建 delegates, 事件处理, 以及使用Windows窗体创建 Windows应用和WPF(以前的Avalon).
阅读完本tutorial估计耗时: 25 分钟
本tutorial 的目标就是了解如何在IronPython中创建 delegates 和事件处理代码, 以及通过Windows 窗体和WPF创建Windows 应用。
在本练习中, 您将会创建一个简单的事件处理,以及了解如何探索(explore)事件处理用法. 这个事件处理即是: FileSystemWatcher - 一个触发( raises )文件系统变化“事件”的组件.
from System.IO import *
w = FileSystemWatcher()
dir(w)
w.Path = "."
def handle(*args): print args
w.Changed += handle
w.Created += handle
w.Deleted += handle
w.EnableRaisingEvents = True
您可以打开文档,随意敲入一些内容,然后保存该文档,看一下这个操作触发了 "Changed" 事件. 之后再删除该文件,看一下"Deleted" 事件被触发.
在这些步骤之后,window 命令行将会显示类似下面的输出:
(System.IO.FileSystemWatcher, <System.IO.FileSystemEventArgs object at 0x03CE0BB8>) (System.IO.FileSystemWatcher, <System.IO.FileSystemEventArgs object at 0x039B3B4D>) (System.IO.FileSystemWatcher, <System.IO.FileSystemEventArgs object at 0x039B3B4D>) (System.IO.FileSystemWatcher, <System.IO.FileSystemEventArgs object at 0x014EF022>)
w.Changed -= handle
w.Created -= handle
w.Deleted -= handle
FileSystemWatcher - 触发事件的对象实例
FileSystemEventArgs - 关于事件触发的信息
使用dir() 去显示事件参数来找到事件所包含的信息:
from System.IO import *
w = FileSystemWatcher()
w.Path = "."
dir(FileSystemEventArgs)
控制台会显示如下输出:
>>> dir(FileSystemEventArgs)
['ChangeType', 'Empty', 'Equals', 'Finalize', 'FullPath', 'GetHashCode', 'GetType', 'MemberwiseClone',
'Name', 'ReferenceEquals', 'ToString', '__class__', '__delattr__', '__doc__', '__getattribute__',
'__hash__', '__init__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__',
'__str__', 'get_ChangeType', 'get_FullPath', 'get_Name']['ChangeType', 'get_ChangeType',
'get_Name', 'FullPath', 'get_FullPath', 'Empty', 'Name']
def handle(w, a): print a.ChangeType, a.FullPath
w.Changed += handle
w.Created += handle
w.Deleted += handle
w.EnableRaisingEvents = True
在该步骤之后, window命令行将会显示如下类似输出:
Created ."New Text Document.txt Changed ."New Text Document.txt Changed ."New Text Document.txt Deleted ."New Text Document.txt
w.Changed -= handle
w.Created -= handle
w.Deleted -= handle
pyevent - 该模块提供Python事件支持
make_event - 该方法返回事件tuple,包括可调用对象(callable object )。该对象允许对事件连接和未连接.
创建事件:
import pyevent
hook,caller = pyevent.make_event()
它返回两个对象。第一个对象允许用户挂钓方法到事件上。第二个对象允许事件持有者(owner) 引发事件. (This allows for the separation of these abilities just like .NET )现在把它放到类中看一下如何使用。
class MyClass(object): OnNewInstance,_NewInstance= pyevent.make_event() def __new__(cls): res = object.__new__(object) MyClass._NewInstance(res)
def NewInst(x): print 'new inst: ', x
MyClass.OnNewInstance += NewInst
a = MyClass()
new inst
MyClass.OnNewInstance -= NewInst
为了开发交互式 Windows 应用, IronPython 须进行初始化. 默认情况下, Python 控制台运行在单一线程下. 当线程等待控制台窗口输入文本时, 被控制台动态创建的Windows 应用不能处理 Windows消息. 因此, 当前应用不会重画自身或处理输入到UI上.
我们提供一个“.py” 文件去初始化IronPython 到Windows Forms 开发如下.
在这个练习中, 您将会通过IronPython控制台动态创建一个简单的Windows Forms 应用.
import winforms
Python 模块自动初始化 (执行) 引用,Windows Forms 初始化代码作为引入声明部分被执行。
from System.Windows.Forms import *
from System.Drawing import *
f = Form()
f.Show()
你可以按下alt-tab或查看运行程序,因为它可能不会跳到您桌面的最上面。
f.Text = "My First Interactive Application"
def click(*args): print args
f.Click += click
单击form 接受事件..
输出类似如下:
>>> (System.Windows.Forms.Form, Text: My First InteractiveApplication, <System.Windows.Forms.MouseEventArgs object at0x02324551>)
因为要进一步开发,现在移除单击处理句柄.
f.Click -= click
dir(MouseEventArgs)
def click(f, a): l = Label(Text = "Hello") l.Location = a.Location f.Controls.Add(l)
f.Click += click
for i in f.Controls: i.Font = Font("Verdana", 15)
for i in f.Controls: i.Text = "Hi"
f.Controls.Clear()
f.Close()
The standalone version of this script is located in wfdemo.py in the Tutorial directory.
这个练习要求安装WPF. Please see prerequisites for more information.
如同Windows Forms, Windows Presentation Foundation 也要求初始化用于支持互动开发. 初始化代码可参见"Tutorial"avalon.py" 文件.
在此练习中, 您可以创建简单的Windows Presentation Foundation 应用.
from avalon import *
w = Window()
w.Show()
您需要按下alt-tab 或查看运行程序,因为它可能不会跳到桌面最上层.
w.Title = "My Avalon Application"
w.SizeToContent = SizeToContent.WidthAndHeight
通过设置窗体属性到 "size to content", the window shrinks.
w.Content = TextBlock()
w.Content.Text = "Hello IronPython!"
w.Content.FontSize = 50
w.Content = None
from avalon import *
w = Window()
w.Show()
w.Content = LoadXaml("calc.xaml")
如果您按从任务1的流程到这个任务, 然后 w.SizeToContent 可被人为设计, but in either case, you may need to manually drag the window's border down and to the right to see the calculator UI.
for n in Walk(w): print n
[ n for n in Walk(w) if isinstance(n, Button) ]
System.Windows.Controls.Button
控制台打印出所有的按钮列表. 为保存按钮列表对象到一个变量中, 使用解析的"_" 变量, 它一直会持有最近的 non-None 值结果:
buttons = _
for b in buttons: b.FontSize *= 2
for b in buttons: b.Foreground = SolidColorBrush(Colors.Blue)
import calculator
calculator.enliven(w)
def __init__(self, controls): (1) self.expression = "" (2) (3) for i in controls: (4) if isinstance(i, Button): (5) if hasattr(self, "on_" + i.Name): (6) i.Click += getattr(self, "on_" + i.Name) (7) elif isinstance(i, TextBox): (8) if i.Name == "Result": (9) self.result = i (10)
self.result.Text = self.expression (11)
方法的"controls" 参数是按钮和文本框列表, 与在步骤3-4中所创建的按钮列表相似. 初始化代码遍历该列表(line 4), 识别按钮(line 5), 并使用按钮的名称("One", "Multiply", " Equals", ...) 去查看calculator属性(方法) ,即通过相应名称 (如:"on_One", "on_Multiply", 和"on_Equals", 一一对应). 如果属性和方法有效, 我们可以挂钓此事件, 使用名称去获取该属性(line 7).
def on_Equals(self, b, e): try: result = str(eval(self.expression)) self.result.Text = result self.expression = result except: self.result.Text = "<<ERROR>>" self.expression = ""
Tutorial 总结
IronPython 提供非常简单的方式开发应用程序,在动态和exploratory方式下. Windows Forms 与 Windows Presentation Foundation (Avalon) 都可以很容易的用最小步骤进行开发. 优势在于其为可视并且可在运行系统上动态修改而不需要重编译.
在本tutorial 中您执行了如下练习:
在本练习中, 您已熟悉了在IronPython中使用 delegates 和 handling events - 开发交互式WinForms 或 Avalon应用的重要部分。接着您动态创建了交互式Windows Forms应用并创建了两个Windows Presentation Foundation应用.
好了,今天的内容就先到这里了(其实到这里,还有一半内容)。 在下一篇中,将会介绍IronPython 中的 COM 协同工作能力。 感兴趣的朋友可以通过EMAIL或在回复中与我联系。