wxPython listctrl insertitem 和 SetItem 一次全部插入

Kev*_*n S 5 wxpython python-3.x

我有一个列表控件,

    self.list = wx.ListCtrl(panel, -1, style=wx.LC_REPORT | wx.LC_NO_HEADER)
    self.list.InsertColumn(col=0, heading='', format=wx.LIST_FORMAT_CENTER, width=150)
    self.list.InsertColumn(col=1, heading='', format=wx.LIST_FORMAT_CENTER, width=450)

    for person in people:
        #this is the issue right here
        index = self.list.InsertItem(0, person.age) #one line to insert an item and get the index, and the next line to update the item at that index... two lines to actually put a full entry in.  
        self.list.SetItem(index=index, column=1, label=person.name)
Run Code Online (Sandbox Code Playgroud)

最初在构造函数中设置 listctrl 效果很好,但是如果我想在运行时动态添加/删除 listctrl 中的项目怎么办?

我遇到过 wx.CallAfter、wx.CallLater、startWorker (来自 wx.lib.delayedresult)和 wx.Timer

如果您查看上面的示例,问题是我有一行插入该项目,另一行更新该项目以在刚刚插入的项目上具有正确的名称。因此,如果我有线程轮流删除和添加项目到 listctrl,如果我插入一个项目,而另一个线程同时插入一个项目,那么我刚刚获得的索引将与更新无关。即我需要一个原子操作来插入一个项目,其中包括插入人的年龄和人的名字。所以我的第一个问题是,有没有办法将列表项的所有信息插入一行?

如果我不能做到这一点,那么我的下一个问题是我怎样才能完成规定的行为?例如,假设有线程随机对顶行进行着色、添加和删除:

    self.color_timer = wx.Timer(self)
    self.Bind(wx.EVT_TIMER, self.item_colorizer, self.color_timer)
    self.red_shown = True
    self.color_timer.Start(500)

    self.delete_timer = wx.Timer(self)
    self.Bind(wx.EVT_TIMER, self.item_deleter, self.delete_timer)
    self.delete_timer.Start(500)


    self.adder_timer = wx.Timer(self)
    self.Bind(wx.EVT_TIMER, self.item_queuer, self.adder_timer)
    self.adder_timer.Start(400)
Run Code Online (Sandbox Code Playgroud)

下面是我用来添加人员、删除人员以及为顶行着色的方法:

def item_queuer(self, event):
    startWorker(consumer=self.item_adder,
                    workerFn=self.person_generator)


def person_generator(self):
    return {'person':random.choice(people)}

def item_adder(self, result):
    res = result.get()
    person = res['person']
    wx.CallAfter(self.list.InsertItem, 0, person.name) # this is the problem right here.  If another thread does a color swap in between this line and the next, then this won't work. 
    wx.CallAfter(self.list.SetItem, index=0, column=1, label=person.name)

def item_deleter(self, event):
    wx.CallAfter(self.list.DeleteItem, 0)

def item_colorizer(self, event):
    if self.color_timer.IsRunning():
        if not self.red_shown:
            wx.CallAfter(self.list.SetItemBackgroundColour, 0, wx.RED)
            wx.CallAfter(self.list.SetItemTextColour, 0, wx.WHITE)
            self.red_shown = True
        else:
            wx.CallAfter(self.list.SetItemBackgroundColour, 0, wx.BLUE)
            wx.CallAfter(self.list.SetItemTextColour, 0, wx.BLACK)
            self.red_shown = False
Run Code Online (Sandbox Code Playgroud)

当我运行这个程序时,实际发生的情况是,我最终得到了部分插入人员的行(只是年龄),并且在插入姓名之前颜色发生了变化。我注意到 listctrl 上的 InsertItem 方法已重载,并提供了一个签名,我可以在其中插入 ListItem,但我也无法使其工作。

    item1 = wx.ListItem()
    item1.SetBackgroundColour(wx.GREEN)
    item1.SetColumn(0)
    item1.SetText(32)
    item1.SetColumn(1)
    item1.SetText('John')
    self.list.InsertItem(item1)
Run Code Online (Sandbox Code Playgroud)

wx._core.wxAssertionError:C++ 断言“rv!= -1”在 wxListCtrl::InsertItem() 中的 ....\src\msw\listctrl.cpp(1730) 处失败:无法在 wxListCtrl 中插入项目