我一直在使用wxPython和UltimateListCtrl为项目创建GUI。对于我的GUI,有一些面板具有UltimateListCtrls,并且遇到了我似乎无法解决的问题。我的GUI包含5列文件列表:一个CheckBox列,一个File Name列,一个File Extension列,一个File Size列和一个ComboBox列。 Example GUI 在列表下方,我有一个按钮,单击该按钮将删除选中了CheckBox的任何行。我的问题是在删除例如第1行并单击最后一行的CheckBox或ComboBox之后出现的。当我收到此错误时:
回溯(最近通话最近): OnSetFocus中的文件“ C:\ Users \ Media_i5 \ PycharmProjects \ PicThings \ venv \ lib \ site-packages \ wx \ lib \ agw \ ultimatelistctrl.py”,行2260 选择= listCtrl.GetItemState(self._itemId,ULC_STATE_SELECTED) 文件“ C:\ Users \ Media_i5 \ PycharmProjects \ PicThings \ venv \ lib \ site-packages \ wx \ lib \ agw \ ultimatelistctrl.py”,行8944,位于GetItemState中 引发Exception(“ GetItemState中的无效项目索引”) 例外:GetItemState中的项目索引无效
当我回溯呼叫时,我发现删除行后,随后每一行的ID /索引都会更新以匹配其在列表中的新位置,但是CheckBox(组合框)的ID /索引却不会。在下面的示例代码中,删除索引1(行2)的行时,索引2的行变为索引1,索引3变为索引2,依此类推。但是,移至索引的行上的Checkbox / ComboBox 1仍具有2的ID /索引。在这种情况下,删除第1行后,如果单击最后一行的CheckBox / ComboBox,则会标记上面的错误,因为Box的索引大于的数目。行。
我希望这是有道理的。下面随附的是一个小的示例代码,它说明了该问题。运行代码,单击图片1的复选框,单击清除按钮,然后单击图片7的复选框。
有人可以帮我弄清楚为什么Box的ID /索引没有像该行那样自动更新吗?
import wx
from wx.lib.agw import ultimatelistctrl as ULC
class Mywin(wx.Frame):
t_col1 = ['PICTURE 1', 'PICTURE 2', 'PICTURE 3', 'PICTURE 4', 'PICTURE 5', 'PICTURE 6', 'PICTURE 7']
t_col4 = ['1', '1', '3', '5', '5', '1', '2']
def __init__(self, parent, title):
wx.Frame.__init__(self, parent)
box2 = wx.BoxSizer(wx.VERTICAL)
title = wx.StaticText(self, wx.ID_ANY, label='Pictures On Frame:')
box2.Add(title, 0, wx.ALL, 5)
self.list = ULC.UltimateListCtrl(self, agwStyle = ULC.ULC_REPORT | ULC.ULC_HAS_VARIABLE_ROW_HEIGHT)
colhead = ["", "File", "Ext", "Size", "Rating"]
colwidth = [30, 300, 45, 45, 45]
for x in range(0, len(colhead)):
self.list.InsertColumn(x, colhead[x], width=colwidth[x])
box2.Add(self.list, 1, wx.EXPAND)
btnSizer2 = wx.BoxSizer(wx.HORIZONTAL)
btnC = wx.Button(self, label="Clear")
btnC.Bind(wx.EVT_BUTTON, self.on_clear)
btnSizer2.Add(btnC, 0, wx.ALL | wx.CENTER, 5)
box2.Add(btnSizer2, 1, wx.EXPAND)
self.SetSizer(box2)
self.SetTitle('Picture Frame Selector')
self.Centre()
self.Maximize()
self.Show()
rb_list = ["1", "2", "3", "4", "5"]
for x in range(0 , len(self.t_col1)):
self.list.InsertStringItem(x, '')
cBox = wx.CheckBox(self.list)
self.list.SetItemWindow(x, 0, cBox)
self.list.SetStringItem(x, 1, self.t_col1[x])
self.list.SetStringItem(x, 2, '.jpg')
dBox = wx.ComboBox(self.list, value=self.t_col4[x], choices=rb_list, style=wx.CB_READONLY)
self.list.SetItemWindow(x, 4, dBox, expand=True)
def on_clear(self, event):
t = 0
for x in range(0, len(self.t_col1)):
if self.list.GetItemWindow(t, 0).IsChecked():
self.list.DeleteItem(t)
else:
t += 1
event.Skip()
if __name__ == "__main__":
ex = wx.App()
Mywin(None, 'Row Delete Issue')
ex.MainLoop()
答案 0 :(得分:0)
您可以通过使用listctrl
t_col1重建list
来解决此问题。
import wx
from wx.lib.agw import ultimatelistctrl as ULC
class Mywin(wx.Frame):
t_col1 = ['PICTURE 1', 'PICTURE 2', 'PICTURE 3', 'PICTURE 4', 'PICTURE 5', 'PICTURE 6', 'PICTURE 7']
t_col4 = ['1', '1', '3', '5', '5', '1', '2']
def __init__(self, parent, title):
wx.Frame.__init__(self, parent)
box2 = wx.BoxSizer(wx.VERTICAL)
title = wx.StaticText(self, wx.ID_ANY, label='Pictures On Frame:')
box2.Add(title, 0, wx.ALL, 5)
self.list = ULC.UltimateListCtrl(self, agwStyle = ULC.ULC_REPORT | ULC.ULC_HAS_VARIABLE_ROW_HEIGHT)
colhead = ["", "File", "Ext", "Size", "Rating"]
colwidth = [30, 300, 45, 45, 45]
for x in range(0, len(colhead)):
self.list.InsertColumn(x, colhead[x], width=colwidth[x])
box2.Add(self.list, 1, wx.EXPAND)
btnSizer2 = wx.BoxSizer(wx.HORIZONTAL)
btnC = wx.Button(self, label="Clear")
btnC.Bind(wx.EVT_BUTTON, self.on_clear)
btnSizer2.Add(btnC, 0, wx.ALL | wx.CENTER, 5)
box2.Add(btnSizer2, 1, wx.EXPAND)
self.SetSizer(box2)
self.SetTitle('Picture Frame Selector')
self.Centre()
self.Maximize()
self.CreateList()
self.Show()
def CreateList(self):
rb_list = ["1", "2", "3", "4", "5"]
for x in range(0 , len(self.t_col1)):
self.list.InsertStringItem(x, '')
cBox = wx.CheckBox(self.list)
self.list.SetItemWindow(x, 0, cBox)
self.list.SetStringItem(x, 1, self.t_col1[x])
self.list.SetStringItem(x, 2, '.jpg')
dBox = wx.ComboBox(self.list, value=self.t_col4[x], choices=rb_list, style=wx.CB_READONLY)
self.list.SetItemWindow(x, 4, dBox, expand=True)
def on_clear(self, event):
for x in range(len(self.t_col1) -1 , -1, -1):
if self.list.GetItemWindow(x, 0).IsChecked():
self.t_col1.pop(x)
self.list.DeleteAllItems()
self.CreateList()
event.Skip()
if __name__ == "__main__":
ex = wx.App()
Mywin(None, 'Row Delete Issue')
ex.MainLoop()
请注意,出于明显的原因,项目从列表中反向移出,我使用list.pop()
,以便可以使用range
而不是list.remove()
的位置
我不允许在choices
列下保存对Rating
所做的更改。