2017-07-23 15 views
0

Je veux créer un ListCtrl personnalisé "MyListCtrlCrafting" qui récupère les données d'une classe différente appelée "DBInterface" (en fait ce n'est pas une vraie base de données, mais un dictionnaire python sophistiqué). Il y a des tutoriels sur la façon de faire cela, j'ai suivi "Python in Action". Les principaux points sont les suivants: hériter de ListCtrl et définir le paramètre de style sur wx.LC_REPORT | wx.LC_SINGLE_SEL | wx.LC_VIRTUAL, appelez SetItemCount() pendant init() et remplacez certaines méthodes.virtual wx.ListCtrl soulève wxAssertionError sur SetItemCount

Pour tester comment cela fonctionne, j'ai fait une petite application qui se compose d'un seul (principal) cadre, le virtuel ListCtrl et une version rudimentaire de DBInterface. Tout fonctionne bien dans ce cadre. Mais quand je connecte les classes de l'application réelle, je reçois un retraçage:

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 

Contrairement à l'application simple, le virtualListCtrl est maintenant profondément imbriquées. Cette erreur peut-elle simplement être produite par de mauvaises connexions à l'intérieur de cette imbrication ou entre DBInterface et ListCtrl? Ou dois-je comprendre comment m_count est calculé, pour résoudre cette erreur? Si oui, comment puis-je lire le fichier _core? J'ai déjà lu sur ListCtrl dans le fichier core.py, mais il ne contient pas les parties pertinentes.

Mon problème avec cette traceback est que je ne comprends pas pourquoi il est déclenché pendant SetItemCount(). Cette méthode devrait être quelque chose comme une définition et comme elle traite des lignes d'une liste, elle devrait accepter des entiers positifs, et peut-être 0, et peut-être aussi -1 pour la norme. Je branche 5, donc ce ne peut pas être le vrai problème qui se passe ici (?)

Toute aide ou conseil est très appréciée!

Le retraçage complet:

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 

Le ListCtrl virtuel (à la fois imprimer de me donner les résultats escomptés):

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

Le DBInterface:

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 
+0

Cette question peut être supprimée car elle n'est pas utile pour les autres. Le problème est que j'ai oublié de définir les paramètres parent et id des panneaux, splitter, etc. – Arbo

Répondre

0

Cette affirmation est fondamentalement une vérifier que l'opération (paramétrer le compte) a réussi, en demandant au contrôle natif combien d'éléments il a (ce qui aurait dû être défini par l'appel d'API antérieur. Il semble que quelque chose ne devrait vraiment pas pouvoir échouer, bien que ce soit évidemment le cas. Peut-être que quelque chose est en train de réinitialiser ou de changer le contrôle natif? Y a-t-il des threads impliqués?

Je n'ai pas une réponse solide pour vous, mais comme conseil, je suggère de prendre le petit échantillon qui fonctionne et de le construire pas à pas jusqu'à ce qu'il corresponde à la hiérarchie des fenêtres et l'environnement et les fonctionnalités de base de cette partie du application complète où elle est cassée. Finalement, il devrait commencer à échouer de la même façon, puis vous saurez ce qui a changé et vous pourrez y regarder de plus près.

+0

Ok merci pour vos conseils. Concernant vos questions: je ne sais pas si quelque chose réinitialise le contrôle, les threads ne sont pas impliqués. Pourriez-vous dire un autre mot sur la lecture du fichier _core? Est-il interdit de lire ou dois-je juste besoin des bonnes lunettes? – Arbo