在wxPython中访问FlexGridSizer中项目的正确方法?

在wxPython中访问FlexGridSizer中项目的正确方法?,python,wxpython,Python,Wxpython,我有一个名为self.grid的FlexGridSizer,有五列,每行有两个TextCtrl、一对RadioButton和一个复选框。检索与这些对象关联的数据的最佳方式是什么?目前我正在成功地使用 # get flat list of all items in flexgridsizer, self.grid children = list(self.grid.GetChildren()) # change list into list of rows (5 items each) tabl

我有一个名为
self.grid
的FlexGridSizer,有五列,每行有两个TextCtrl、一对RadioButton和一个复选框。检索与这些对象关联的数据的最佳方式是什么?目前我正在成功地使用

# 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())
这就给我留下了
,一个行列表,每个行有五个元素,每个元素都是相关数据:text代表TextCtrl,bool代表RadioButton,以及(label,bool)代表CheckBox。 这似乎完成了任务,但感觉不太对劲


有没有更好的方法从FlexGridSizer恢复数据?或者,我是否应该对此布局使用不同的大小设定器/控件?(我尝试了UltimateListCtrl,但它有bug/实际上没有完成我需要的操作)。

你不应该真的这么做。。相反,您应该在创建时创建对它们的引用

self.widgetTable = []
for row in dataSet:
   self.widgetTable.append([wx.TextCtrl(self,-1,value) for value in row])
然后通过那个访问他们

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

因为您有工作代码,并且似乎在询问编码风格,所以您可能有幸询问代码审查

话虽如此,你这里的东西并不可怕。我认为
isinstance()
非常难看,所以当我做类似的事情时,我按照小部件的顺序来做,因为我知道每5个小部件都是我想要的。也许你可以用类似的方法?或者使用
try…except
结构来避免
isinstance

这里有两种方法,第一种是基于小部件的顺序,第二种只是猜测如何检索信息

方法1:因此,如果您的小部件有规则的顺序,您可以这样做:(可怕的变量名仅用于演示)

其中
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
你可以说第二种方法更像是“pythonic”,但这有待讨论。此外,如果没有一些巧妙的技巧,最后只剩下一个列表,这可能不适合你

关于您的解决方案的一些注意事项:

  • self.grid.GetChildren()是iterable,因此在将其用作iterable之前,不需要将其转换为列表
  • 您可以将顺序
    if
    语句更改为
    if…elif…(else)
    构造,但在这种情况下,这并没有什么大不了的,因为您不希望任何小部件进行多个测试

希望这能有所帮助

只是出于好奇,为什么要像这样从
TextCtrl
中检索值?
GetValue()
有什么问题吗?谢谢,我本应该使用
GetValue()
的,但我有一个错误的印象,我不得不这样做,因为它是一个多行TextCtrl,因为我只是在看这个方法。这是我希望听到的。这确实意味着我最终使用了
copy.deepcopy()
,因为我的应用程序运行了FlexGridSizer的多次迭代。感谢您的提示,您的方法1无疑是对我的代码的改进(每行的顺序相同)。我肯定应该在后续的
isinstance()
调用中使用
elif
。我还希望
GetChildren()
是可编辑的,但我需要它是一个列表,以便在顶部的列表理解中对其进行切片(否则会抛出
TypeError
)。
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