我正在教授一门使用Python编程和GUI开发的入门课程,并且发现对于刚开始编程的学生来说,最简单的解决方案是使用Visual Studio进行GUI开发。
虽然c#和VB的GUI开发经验是愉快的,但我找不到用IronPython做同样的方法。我安装了包含Visual Studio工具的IronPython 2.7.1,并创建了一个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 Worldn'
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的体验。
在IronPython 2.7中LoadComponent方法将连接所有与XAML UI元素同名的属性。如果你正在使用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两个属性来访问UI元素:
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并给UI元素一个名字时,null引用异常。
您需要遍历所有对象,并使用如下函数创建更容易理解的引用。
#
# 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查看上述代码和完整示例。