Разработка графического интерфейса с IronPython и Visual Studio 2010 - PullRequest
14 голосов
/ 02 мая 2011

Я преподаю вводный класс по программированию и разработке GUI с использованием Python и обнаружил, что наименее подавляющее решение для начинающих студентов в программировании - это использование Visual Studio для разработки GUI.

В то время как разработка GUIопыт работы с C # и VB приятен, я не мог найти способ сделать то же самое с IronPython.Я установил IronPython 2.7.1, который включает в себя инструменты Visual Studio, и создал проект WPF IronPython.

Я могу использовать конструктор форм WPF так же, как 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 World\n'


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 GUI, которые предлагают опыт, аналогичный Visual Studio.

Ответы [ 2 ]

6 голосов
/ 02 мая 2011

В 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 и датьПользовательский интерфейс имя.

0 голосов
/ 02 мая 2011

Вам нужно пройтись по всем объектам и создать более легкие / понятные ссылки, используя такую ​​функцию, как.

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

...