使用IronPython和Visual Studio 2010进行GUI开发
我正在教一门关于编程和图形用户界面(GUI)开发的入门课程,使用的是Python。我发现,对于刚接触编程的学生来说,使用Visual Studio进行GUI开发是最简单易懂的选择。
虽然用C#和VB进行GUI开发的体验很不错,但我找不到用IronPython做到同样效果的方法。我安装了IronPython 2.7.1,它包含了Visual Studio的工具,并创建了一个WPF IronPython项目。
我可以像使用VB和C#一样使用WPF表单设计器,但我找不到一种方便的方式(也就是学生能理解的方式)来访问GUI元素。例如,在VB中,你可以通过元素的名字来引用它们,然后修改它们的属性。而我在IronPython中能做到的最好方式(我不打算向学生展示)是这样的:
import wpf
from System.Windows import Application, Window
class MyWindow(Window):
def __init__(self):
wpf.LoadComponent(self, 'WpfApplication3.xaml')
def Button_Click(self, sender, e):
#This is the only way I could find in which I can
#access an element and modify its properties
self.Content.Children[1].Text += 'Hello World\n'
if __name__ == '__main__':
Application().Run(MyWindow())
我注意到GUI元素没有名字,而且每当我尝试手动修改XAML来给元素命名时,Visual Studio就会崩溃。以下是一个简单框架的生成XAML,其中包含一个按钮和一个文本区域:
<Window
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="WpfApplication3" Height="300" Width="300">
<Grid>
<Button Content="Button" Height="23" HorizontalAlignment="Left" Margin="103,226,0,0" VerticalAlignment="Top" Width="75" Click="Button_Click" />
<TextBox Height="182" HorizontalAlignment="Left" Margin="24,21,0,0" VerticalAlignment="Top" Width="237" />
</Grid>
</Window>
如果能提供一些帮助,让学生更容易理解这部分内容,我会非常感激。我也欢迎其他关于Python GUI开发的建议,希望能提供类似于Visual Studio的体验。
2 个回答
你需要遍历所有的对象,并使用一个函数来创建更简单、更易懂的引用。
#
# Waddle returns a dictionary of Control types e.g. listbox, Button.
# Each Entry is a dictionary of Control Instance Names i.e.
# controls['Button']['NewSite'] returns the button control named NewSite
# Controls should have Unique names and only those with a Name attrib set
# will be included.
#
def Waddle(c, d):
s = str(c.__class__)
if "System.Windows.Controls." in str(c) and hasattr(c,"Name") and c.Name.Length>0:
ControlType = s[s.find("'")+1:s.rfind("'")]
if ControlType not in d:
d[ControlType] = {}
d[ControlType][c.Name] = c
if hasattr(c,"Children"):
for cc in c.Children:
Waddle(cc, d)
elif hasattr(c,"Child"):
Waddle(c.Child, d)
elif hasattr(c,"Content"):
Waddle(c.Content, d)
if __name__ == "__main__":
xr = XmlReader.Create(StringReader(xaml))
win = XamlReader.Load(xr)
controls = {}
Waddle(win, controls)
#Make all Named buttons do something!
for butt in controls['Button']:
controls['Button'][butt].Click += sayhello
#Make one button do something.
controls['Button']['NewSite'].Click += sayhello2
Application().Run(win)
可以查看这个链接 http://www.ironpython.info/index.php/XAML_GUI_Events_Example,里面有上面代码的完整示例。
在IronPython 2.7中,wpf.LoadComponent这个方法会自动把和XAML界面元素同名的属性连接起来。如果你用的是IronPython 2.6,那就需要按照WombatPM的建议来写代码。所以在IronPython 2.7中,如果你使用以下的XAML:
<Window
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="IronPyWpf" Height="300" Width="300">
<Grid>
<Button x:Name="button" Content="Button" Height="23" HorizontalAlignment="Left" Margin="103,226,0,0" VerticalAlignment="Top" Width="75" />
<TextBox x:Name="textbox" Height="182" HorizontalAlignment="Left" Margin="24,21,0,0" VerticalAlignment="Top" Width="237" />
</Grid>
</Window>
那么你可以定义两个属性,分别叫做button和textbox,这样就能访问这些界面元素了:
class MyWindow(Window):
def __init__(self):
wpf.LoadComponent(self, 'IronPyWpf.xaml')
self._button.Content = 'My Button'
self._textbox.Text = 'My Text'
def get_button(self):
return self._button
def set_button(self, value):
self._button = value
button = property(get_button, set_button)
def get_textbox(self):
return self._textbox
def set_textbox(self, value):
self._textbox = value
textbox = property(get_textbox, set_textbox)
其实,你甚至可以进一步简化代码,直接去掉属性的定义:
class MyWindow(Window):
def __init__(self):
wpf.LoadComponent(self, 'IronPyWpf.xaml')
self.button.Content = 'My Button'
self.textbox.Text = 'My Text'
不过不幸的是,正如你已经看到的,Visual Studio在你尝试编辑XAML并给界面元素命名时,似乎会崩溃,出现空引用异常。