2011-05-02 69 views
13

我正在教一個使用Python進行編程和GUI開發的入門級課程,並且發現對於新編程的學生來說,最不壓倒的解決方案是使用Visual Studio進行GUI開發。使用IronPython和Visual Studio 2010進行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 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的體驗。

+1

我發現使用PyQt4與Qt設計器比使用Visual Studio更容易(對我來說),因爲它輕巧簡單。我嘗試了Visual Studio幾年,但它非常臃腫。 – Blender 2011-05-02 05:51:58

回答

5

在IronPython 2.7中,wpf.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> 

然後你就可以定義兩個屬性名爲按鈕和文本框來訪問的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中似乎崩潰了,因爲你已經看到,有一個空引用異常,當您試圖ŧ o編輯XAML併爲UI元素命名。

+0

這個答案是正確的。崩潰聽起來像一個錯誤,我很高興在Visual Studio的Python工具(pythontools.codeplex.com)中修復它。我爲此打開了一個錯誤 - http://pytools.codeplex.com/workitem/158,我會在那裏修復它,或者確保它沒有重新生成。一般來說,我建議使用PTVS而不是內置工具w/IronPython 2.7,因爲它們在這一點上更積極地維護(所以我們通常會說很快修復錯誤)。 – 2011-05-04 01:17:01

+0

我無法重現問題瓦特/ PTVS,所以它看起來像它在那裏修復(或者我需要更多的信息,你正在做什麼來改變名稱 - 我試過它w/x:名稱,名稱和編輯通過UI)。一種可能性是這是IpyTools的老版本,因爲我記得一些崩潰的錯誤,後來得到修復。 – 2011-05-04 23:50:12

+0

只有使用IronPython 2.7安裝程序附帶的Visual Studio工具鍵入x:Name屬性的名稱時纔會出現此問題。 Python工具是可以的。我使用Python工具的唯一問題是我無法運行WPF應用程序。它看起來像是無法導入wpf庫。 – 2011-05-05 20:21:51

0

您需要遍歷所有對象,並使用類似的函數創建更容易理解的引用。

# 
# 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爲上面的代碼和一個完整的例子。

相關問題