Skip to main content
 首页 » 编程设计

python之wxPython ListCtrl 列忽略特定字段

2025年05月04日9birdshome

我正在重写这篇文章以澄清一些事情并为我遇到问题的虚拟列表提供完整的类定义。该类定义如下:

from wx import ListCtrl, LC_REPORT, LC_VIRTUAL, LC_HRULES, LC_VRULES, \ 
  EVT_LIST_COL_CLICK, EVT_LIST_CACHE_HINT, EVT_LIST_COL_RIGHT_CLICK, \ 
  ImageList, IMAGE_LIST_SMALL, Menu, MenuItem, NewId, ITEM_CHECK, Frame, \ 
  EVT_MENU 
 
class VirtualList(ListCtrl): 
  def __init__(self, parent, datasource = None, 
               style = LC_REPORT | LC_VIRTUAL | LC_HRULES | LC_VRULES): 
    ListCtrl.__init__(self, parent, style = style) 
 
    self.columns = [] 
    self.il = ImageList(16, 16) 
 
    self.Bind(EVT_LIST_CACHE_HINT, self.CheckCache) 
    self.Bind(EVT_LIST_COL_CLICK, self.OnSort) 
 
    if datasource is not None: 
      self.datasource = datasource 
      self.Bind(EVT_LIST_COL_RIGHT_CLICK, self.ShowAvailableColumns) 
 
      self.datasource.list = self 
 
      self.Populate() 
 
  def SetDatasource(self, datasource): 
    self.datasource = datasource 
 
  def CheckCache(self, event): 
    self.datasource.UpdateCache(event.GetCacheFrom(), event.GetCacheTo()) 
 
  def OnGetItemText(self, item, col): 
    return self.datasource.GetItem(item, self.columns[col]) 
 
  def OnGetItemImage(self, item): 
    return self.datasource.GetImg(item) 
 
  def OnSort(self, event): 
    self.datasource.SortByColumn(self.columns[event.Column]) 
    self.Refresh() 
 
  def UpdateCount(self): 
    self.SetItemCount(self.datasource.GetCount()) 
 
  def Populate(self): 
    self.UpdateCount() 
 
    self.datasource.MakeImgList(self.il) 
 
    self.SetImageList(self.il, IMAGE_LIST_SMALL) 
 
    self.ShowColumns() 
 
  def ShowColumns(self): 
    for col, (text, visible) in enumerate(self.datasource.GetColumnHeaders()): 
      if visible: 
        self.columns.append(text) 
        self.InsertColumn(col, text, width = -2) 
 
  def Filter(self, filter): 
    self.datasource.Filter(filter) 
 
    self.UpdateCount() 
 
    self.Refresh() 
 
  def ShowAvailableColumns(self, evt): 
    colMenu = Menu() 
 
    self.id2item = {} 
 
    for idx, (text, visible) in enumerate(self.datasource.columns): 
      id = NewId() 
 
      self.id2item[id] = (idx, visible, text) 
 
      item = MenuItem(colMenu, id, text, kind = ITEM_CHECK) 
      colMenu.AppendItem(item) 
 
      EVT_MENU(colMenu, id, self.ColumnToggle) 
 
      item.Check(visible) 
 
    Frame(self, -1).PopupMenu(colMenu) 
 
    colMenu.Destroy() 
 
  def ColumnToggle(self, evt): 
    toggled = self.id2item[evt.GetId()] 
 
    if toggled[1]: 
      idx = self.columns.index(toggled[2]) 
 
      self.datasource.columns[toggled[0]] = (self.datasource.columns[toggled[0]][0], False) 
 
      self.DeleteColumn(idx) 
 
      self.columns.pop(idx) 
 
    else: 
      self.datasource.columns[toggled[0]] = (self.datasource.columns[toggled[0]][0], True) 
 
      idx = self.datasource.GetColumnHeaders().index((toggled[2], True)) 
 
      self.columns.insert(idx, toggled[2]) 
 
      self.InsertColumn(idx, toggled[2], width = -2) 
 
    self.datasource.SaveColumns() 

我添加了允许列切换的功能,这有助于我描述我遇到的问题。在我的应用程序中此类的第三个实例中,索引 1 处的列将不显示字符串值。整数值显示正确。如果我将打印语句添加到我的 OnGetItemText 方法中,这些值会正确显示在我的控制台中。此行为在此类的前两个实例中不存在,并且我的类不包含任何与值显示相关的类型检查代码。

wxPython 用户组的某个人建议我创建一个独立示例来演示这个问题(如果可以的话)。我正在努力,但还没有时间创建不依赖于数据库访问的示例。任何建议或意见将不胜感激。我正在为此撕毁我的头发。

请您参考如下方法:

您是否在构建虚拟列表控件的 wxPython 演示代码?您需要做一些簿记工作,例如设置 ItemCount 属性。

关于您的 OnGetItemText 方法的一条评论:由于没有其他返回语句,如果数据为 None,它将返回 None,因此您的测试无效。

返回数据或 "" 怎么样?