我想创建一个自定义 ListCtrl“MyListCtrlCrafting”,它从另一个名为“DBInterface”的类中提取数据(实际上它不是一个真正的数据库,而是一个复杂的 python 字典)。有关于如何做到这一点的教程,我遵循“Python in Action”。要点是:从 ListCtrl 继承,并将样式参数设置为 wx.LC_REPORT | wx.LC_SINGLE_SEL | wx.LC_VIRTUAL,在init () 期间调用 SetItemCount() 并覆盖一些方法。
为了测试它是如何工作的,我制作了一个小应用程序,它只包含一个(主)框架、虚拟 ListCtrl 和一个基本版本的 DBInterface。在此设置中一切正常。但是当我连接真实App的类时,我得到了一个Traceback:
Traceback (most recent call last):
File "DesktopCrafter.py", line 198, in <module>
controller = AppCtrl()
File "DesktopCrafter.py", line 186, in __init__
self.frame = GUI.MainWindow(back_end=self.back_end, crafting_controller=self.crafting_controller, parent=None, title='Desktop Crafter')
...
self.view = MyListCtrlCrafting(name='crafting-hand', back_end=self.db, crafting_controller=self.cc, parent=self, id=wx.ID_ANY)
File "d:\workspace-fun\DesktopCrafter\dc\util\DCUI.py", line 107, in __init__
self.bindData()
File "d:\workspace-fun\DesktopCrafter\dc\util\DCUI.py", line 121, in bindData
self.SetItemCount(count)
wx._core.wxAssertionError: C++ assertion "m_count == ListView_GetItemCount(GetHwnd())" failed at ..\..\src\msw\listctrl.cpp(3120) in wxListCtrl::SetItemCount(): m_count should match ListView_GetItemCount
与简单的 App 相比,virtualListCtrl 现在嵌套得很深。此错误是否仅由此嵌套内部或 DBInterface 和 ListCtrl 之间的错误连接产生?还是我必须了解如何计算 m_count 才能解决此错误?如果是这样,我怎样才能读取 _core 文件?我已经在 core.py 文件中阅读了有关 ListCtrl 的信息,但它不包含相关部分。
我对这个回溯的问题是我不明白为什么在 SetItemCount() 期间会引发它。这个方法应该类似于定义,因为它处理列表的行,它应该接受正整数,可能是 0,也可能是标准的 -1。我插入了 5,所以这不是这里发生的真正问题(?)
非常感谢任何帮助或提示!
完整的追溯:
Traceback (most recent call last):
File "DesktopCrafter.py", line 198, in <module>
controller = AppCtrl()
File "DesktopCrafter.py", line 186, in __init__
self.frame = GUI.MainWindow(back_end=self.back_end, crafting_controller=self.crafting_controller, parent=None, title='Desktop Crafter')
File "d:\workspace-fun\DesktopCrafter\dc\util\DCUI.py", line 285, in __init__
self.InitUI()
File "d:\workspace-fun\DesktopCrafter\dc\util\DCUI.py", line 299, in InitUI
self.panel = MainPanel(back_end=self.db, crafting_controller=self.cc)
File "d:\workspace-fun\DesktopCrafter\dc\util\DCUI.py", line 251, in __init__
self.splitter = MySplitter(back_end=back_end, crafting_controller=crafting_controller)
File "d:\workspace-fun\DesktopCrafter\dc\util\DCUI.py", line 229, in __init__
self.l_frame = LPanel(back_end=back_end, crafting_controller=crafting_controller)
File "d:\workspace-fun\DesktopCrafter\dc\util\DCUI.py", line 188, in __init__
self.panel = CraftingPanel(back_end=back_end, crafting_controller=crafting_controller, *args, **kwargs)
File "d:\workspace-fun\DesktopCrafter\dc\util\DCUI.py", line 154, in __init__
self.view = MyListCtrlCrafting(name='crafting-hand', back_end=self.db, crafting_controller=self.cc, parent=self, id=wx.ID_ANY)
File "d:\workspace-fun\DesktopCrafter\dc\util\DCUI.py", line 107, in __init__
self.bindData()
File "d:\workspace-fun\DesktopCrafter\dc\util\DCUI.py", line 121, in bindData
self.SetItemCount(count)
wx._core.wxAssertionError: C++ assertion "m_count == ListView_GetItemCount(GetHwnd())" failed at ..\..\src\msw\listctrl.cpp(3120) in wxListCtrl::SetItemCount(): m_count should match ListView_GetItemCount
虚拟 ListCtrl (两个打印都给了我预期的结果):
class MyListCtrlCrafting(wx.ListCtrl):
def __init__(self, name, back_end, crafting_controller, *args, **kwargs):
wx.ListCtrl.__init__(self, style=wx.LC_REPORT | wx.LC_SINGLE_SEL | wx.LC_VIRTUAL, *args, **kwargs)
self.name = name
self.db = back_end
self.cc = crafting_controller
#print(self.db.retrieveValue(['player', self.name]))
self.Bind(wx.EVT_LIST_CACHE_HINT, self.DoCacheItems)
self.bindData()
self.InsertColumn(0, "Slot")
self.InsertColumn(1, "Item")
self.InsertColumn(2, "Amount")
print("initialized MyListCtrl")
def bindData(self):
data = self.db.retrieveValue(['player', self.name])
count = len(data)
#print(count)
self.itemDataMap = {i: ('slot'+str(i+1), data[str(i)]['item'], data[str(i)]['amount']) for i in range(count)}
self.SetItemCount(count)
def DoCacheItems(self, e):
self.db.updateCache(e.GetCacheFrom(), e.GetCacheTo())
def OnGetItemText(self, row_no, col_no):
data = self.db.retrieveValue(['player', self.name, str(row_no)])
return data[col_no]
def OnGetItemAttr(self, item): return None
def OnGetItemImage(self, item): return -1
def OnBackEndUpdated(self):
self.bindData()
self.RefreshItems(0, self.GetItemCount())
数据库接口:
class DBInterface(dict):
def __init__(self, path, *args, **kwargs):
super(DBInterface, self).__init__(*args, **kwargs)
self.path = path
def load(self):
with open(self.path, 'r') as f:
try:
self.update(json.loads(f.read()))
except Exception as e:
print(e); print(self.path)
def save(self):
self.path.ensure()
with open(self.path, 'w') as f:
f.write(json.dumps(self))
def retrieveValue(self, path):
a = self
for i in range(len(path)):
a = a[path[i]]
return a