【问题标题】:wxPython UltimateListCtrl - deleting last index causes error on IsHighlightedwxPython UltimateListCtrl - 删除最后一个索引会导致 IsHighlighted 出错
【发布时间】:2022-05-18 22:34:05
【问题描述】:

我在我的 GUI 中使用 UltimateListCtrls。我在小部件中添加了一个右键菜单,并在该菜单中添加了一个删除按钮。如果用户按下按钮,鼠标所在的索引将被删除。

问题似乎在于,在此之后列表尝试重新创建选择/突出显示,但是因为没有比索引超出范围之前少一行。

如何防止此错误?我还尝试删除所有项目并重新创建列表,但在“DeleteAllItems”函数中也会发生错误。

错误:

Traceback(最近一次调用最后一次):文件 “...\lib\site-packages\wx\lib\agw\ultimatelistctrl.py”,第 7723 行,在 鼠标上 如果不是 self.IsHighlighted(current):文件“...\lib\site-packages\wx\lib\agw\ultimatelistctrl.py”,第 6883 行,在 突出显示 ld = self.GetLine(line) 文件“…\lib\site-packages\wx\lib\agw\ultimatelistctrl.py”,第 6438 行,在 获取线 return self._lines[n] IndexError: list index out of range

我的列表是这样创建的:

    agwStyle = (ULC.ULC_HAS_VARIABLE_ROW_HEIGHT | wx.LC_REPORT | wx.LC_VRULES | wx.LC_HRULES | wx.LC_SINGLE_SEL)


    self.list_components = ULC.UltimateListCtrl(component_masterPanel, wx.ID_ANY, agwStyle=agwStyle)
    self.list_components.InsertColumn(0, 'Component', width=90)
    self.list_components.InsertColumn(1, 'Name', width=120)

删除索引的代码:

def OnRightClick(self, event):
    index = event.GetIndex()        
    widget = event.GetEventObject()

    widget.Select(index,True)


    item = widget.GetItem(index, col=0)
    comp_id = item.GetText()

    # Create menu
    popupmenu = wx.Menu()       
    menuItem_1 = popupmenu.Append(-1, 'Delete')           
    wrapper_1 = lambda event: self.OnDeleteComponent(event, index, widget)           
    self.Bind(wx.EVT_MENU, wrapper_1, menuItem_1)  

    # Show menu
    self.PopupMenu(popupmenu, self.ScreenToClient(wx.GetMousePosition()))


def OnDeleteComponent(self, event, index=None, widget=None):
    widget.DeleteItem(index)

Rolf 请看我的更新版本:

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)

            self.Bind(wx.EVT_LIST_ITEM_RIGHT_CLICK, self.OnRightClick, self.list)


    def OnRightClick(self, event):
        index = event.GetIndex()        
        widget = event.GetEventObject()                

        popupmenu = wx.Menu()       
        menuItem_1 = popupmenu.Append(-1, 'Delete')           
        wrapper_1 = lambda event: self.OnDeleteComponent(event, index, widget)           
        self.Bind(wx.EVT_MENU, wrapper_1, menuItem_1)

        self.PopupMenu(popupmenu, self.ScreenToClient(wx.GetMousePosition()))


    def OnDeleteComponent(self, event, index=None, widget=None):
        widget.DeleteItem(index)


    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()

【问题讨论】:

  • 这个错误似乎已经存在一段时间了,ULC 的内部索引似乎没有持续更新。见:stackoverflow.com/questions/52286106/…
  • 感谢您的回答,我也尝试重新创建列表。但是在我调用“widget.DeleteAllItems()”的时候,也会发生错误。由于它不是很关键,有没有一种很好的方法来捕捉该错误并使其不可见?
  • 错误是在DeleteAllItems()函数内还是在重建列表时出现?我没有看到这种行为。
  • 重建列表时出现错误,UltimateListCtrl代码中的“isHighlighted”函数导致错误。突出显示似乎没有正确更新到新列表。所以只有当最后一个索引或者列表的最后一项被删除时才会出现错误。
  • 我无法在我的链接 (wxpython 4.1.0 gtk2) 中给出的示例中重现该问题

标签: python python-3.x user-interface wxpython


【解决方案1】:

在编写代码时,我遇到了完全相同的错误。

我还从wx.Menu() 事件中调用DeleteAllItems(),并收到错误“IndexError: list index out of range”。

我找到了解决方案。 要消除此类错误,必须使用wx.CallAfter 调用从发生删除的wx.EVT_MENU 事件调用的函数。

你的例子:

wx.CallAfter(widget.DeleteItem, index)

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-04-09
    • 1970-01-01
    • 2021-11-12
    • 1970-01-01
    • 2020-04-22
    • 1970-01-01
    相关资源
    最近更新 更多