2014-03-03 21 views
2

我有一個叫做self.grid的FlexGridSizer,有五列,每行有兩個TextCtrl的一對RadioButton和一個CheckBox。檢索與這些對象相關的數據的最佳方法是什麼?目前,我成功地利用在wxPython中訪問FlexGridSizer中項目的正確方法?

# get flat list of all items in flexgridsizer, self.grid 
children = list(self.grid.GetChildren()) 

# change list into list of rows (5 items each) 
table = [children[i:i+5] for i in range(0, len(children), 5)] 

# parse list of 'sizeritems' to extract content 
for x in range(len(table)): 
    for y in range(len(table[x])): 
     widget = table[x][y].GetWindow() 
     if isinstance(widget, wx.TextCtrl): 
      text = "" 
      for num in range(widget.GetNumberOfLines()): 
       text += widget.GetLineText(num) 
      table[x][y] = text 
     if isinstance(widget, wx.RadioButton): 
      table[x][y] = widget.GetValue() 
     if isinstance(widget, wx.CheckBox): 
      table[x][y] = (widget.GetLabel(), widget.GetValue()) 

這給我留下了table,行的每個五行,每一個項目是相關數據的列表:文本TextCtrl,布爾的單選按鈕,和(標籤,布爾)的複選框。 這似乎完成了工作,但它不感覺沒錯。

有沒有更好的方法從FlexGridSizer恢復數據?另外,我應該爲這個佈局使用不同的尺寸/控制器嗎? (我試過UltimateListCtrl,但它是越野車/並沒有真正做我所需要的)。

+0

只是出於好奇,爲什麼你檢索你的'''TextCtrl'''這樣的價值呢? '''GetValue()'''有什麼問題? – wnnmaw

+0

謝謝,我應該使用'GetValue()',但我的錯誤印象是我必須這樣做,因爲它是一個多行TextCtrl,因爲我只查看這個[文檔頁面上的方法](http://wxpython.org/Phoenix/docs/html/TextCtrl.html)。 – mark

回答

0

你不應該真的那樣做..而不是創建時

self.widgetTable = [] 
for row in dataSet: 
    self.widgetTable.append([wx.TextCtrl(self,-1,value) for value in row]) 

然後通過

self.widgetTable[0][0].GetValue() 
+0

這就是我希望聽到的。這意味着我最終使用'copy.deepcopy()',因爲我的應用程序通過FlexGridSizer的多次迭代運行。 – mark

0

訪問它們既然你已經工作的代碼,並且似乎是你應該建立對它們的引用詢問編碼風格,您可能會在Code Review上碰到一些問題。

這就是說,你在這裏有什麼不是太可怕。我認爲isinstance()是非常醜陋的,所以當我做了這樣的事情時,我按照小部件的順序走,因爲我知道每個小部件都是我想要的。也許你可以使用類似的方法?或者使用try...except結構來避免isinstance

因此,這裏有兩種方法,第一種方法基於您的小部件的順序,第二種方法只是猜測如何檢索信息。

方法1:所以,如果你的部件有定期的順序,你可以做這樣的事情:(僅用於演示可怕的變量名)

list_of_one_type_of_widget = map(lambda x: x.GetWindow(), self.grid.GetChildren())[::k] 
list_of_values_for_first_type = map(lambda x: x.GetValue(), list_of_one_type_of_widget) 

list_of_another_type_of_widget = map(lambda x: x.GetWindow(), self.grid.GetChildren())[1::k] 
list_of_values_for_first_type = map(lambda x: (x.GetLabel(), x.GetValue()), list_of_another_type_of_widget) 

哪裏k是你有小部件類型的數量。當我遇到這個問題時,我就是這樣解決問題的,我認爲它非常漂亮而且非常簡潔。您剩下的每個類型的窗口小部件都有一個列表,這樣一來,如果依賴於窗口小部件,處理過程將變得很簡單。你也可以很容易地將它重新制作成表格。請務必注意第二張如何與[1::k]而不是[::k]切片。每個後續的小部件類型將需要比以前更大。

方法2:如果沒有正常秩序,你可以做這樣的事情:

list_of_values = [] 
for widget in map(lambda x: x.GetWindow(), self.grid.GetChildren()): 
    try: 
     list_of_values.append(widget.GetValue()) 
    except: 
     #Same as above, but with the appropriate Get function. If there multiple alternatives, just keep nesting try...except blocks in decrease order of commonness 

你可以做的是第二種方法更「Python化」的情況,但是這以供辯論。另外,如果沒有一些聰明的技巧,最後只剩下一個列表,這可能不適合你。

您的解決方案的一些注意事項:

  • self.grid。GetChildren()是可迭代的,因此在使用它作爲迭代之前,不需要將其轉換爲列表。
  • 您可以將順序if語句更改爲if...elif...(else)構造,但它在這方面並不是什麼大事因爲你的情況下不要指望任何小部件多個測試

希望這有助於

+0

感謝您的提示,您的方法1無疑是對我的代碼的改進(它們在每行中的排列順序相同)。我肯定應該在後續的'isinstance()'調用中使用'elif'。我也希望'GetChildren()'是可迭代的,但我需要它成爲一個列表,以便將它放在頂部的列表理解中(否則它會拋出'TypeError')。 – mark

相關問題