Разработка GUI с помощью IronPython и Visual Studio 2010
Я преподаю вводный класс по программированию и разработке GUI с использованием Python и обнаружил, что наименее подавляющим решением для студентов, новых в программировании, является использование Visual Studio для разработки GUI.
хотя опыт разработки GUI с C# и VB приятен, я не мог найти способ сделать то же самое с IronPython. Я установил IronPython 2.7.1, который включает инструменты Visual Studio, и создал проект WPF IronPython.
Я могу использовать WPF form designer так же, как VB и C#, однако, я не мог найти удобный способ (т. е. понятный для студентов), в котором можно было бы получить доступ к элементам 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 не получают имени и Visual Studio аварийно завершает работу всякий раз, когда я пытаюсь чтобы вручную изменить XAML для имен элементов. Вот сгенерированный 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, которые предлагают опыт, подобный Visual Studio.
2 ответов
В 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 и дать элементам пользовательского интерфейса имя.
вам нужно пройти через все объекты и создать более простые/понятные ссылки, используя такую функцию, как.
#
# 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 для приведенного выше кода и полного примера.