Разработка 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 для приведенного выше кода и полного примера.