Search code examples
pythonmultithreadingwxpython

wxPython grid function suddenly stops being *callable* after the first pass to wx.CallAfter


I use: import wx.grid as gridlib and then I do this inside the class that inherits wx.Panel:

self.grid = gridlib.Grid(self)
self.grid.CreateGrid(10000, 17)

And it creates a large grid. Now when I do this in a function that is being called by another thread:

current_line  = 1
wx.CallAfter(self.grid.SetCellValue(current_line - 1, 1, "SMTH"))
current_line += 1
wx.CallAfter(self.grid.SetCellValue(current_line - 1, 1, "SMTH"))

On the second wx.CallAfter I get:

assert callable(callableObj), "callableObj is not callable" AssertionError: callableObj is not callable

So it means the object loses its method? I mean functions in python are objects, so the SetCellValue object is somehow deleted?


Solution

  • The code is not doing what you think it is doing. wx.CallAfter is basically called by having several arguments. The first argument is a reference to the function/method CallAfter should call, the following arguments are the arguments which shall be passed on to the function/method reference in the first argument (see wx._core):

    def CallAfter(callableObj, *args, **kw):
    

    You pointed already to the complete source of wx.CallAfter in this post.

    What you are doing instead is calling the method/function yourself and passing the result to CallAfter. Therefore the first call seems to work, because calling happens first and CallAfter fails later on (because it gets the result of ….SetCellValue(…) instead a reference.

    So you should simply write instead for both lines:

    wx.CallAfter(self.grid.SetCellValue, current_line - 1, 1, "SMTH")