Why do I have to force refresh the grid when I change cell background consecutively?

Please see the code below:

class upgradeThread (threading.Thread):
def init(self, threadID, name, counter, grid, row, col):
threading.Thread.init(self)
self.threadID = threadID
self.name = name
self.grid = grid
self.row = row
self.col = col
self.counter = counter
def run(self):
print "Starting " + self.name
upgrade_crew(self.name, 1, self.grid, self.row, self.col)
print "Exiting " + self.name

def upgrade_cell(threadName, delay, grid, row, col):
if threadName == “Paint”:

    grid.SetCellBackgroundColour(row, col, "RED")
    print "painted red"   
    time.sleep(delay)
    print "slept 1 sec"
    grid.SetCellBackgroundColour(row, col, "WHEAT")
    print "painted wheat"
else:
    grid.SetCellValue(row, col, "upgraded") 

thread1 = upgradeThread(1, “Paint”, 1, grid_object, 1, 3)
thread2 = upgradeThread(2, “Upgrade”, 2, grid_object, 1, 3)
thread1.start()
thread2.start()

This uses a threading, when it is changing the content of a cell, it also changes the background twice, at the same time.

1- It writes “upgraded” to the cell, and paints it red
2- It waits 1 second
3- Then it paints the cell to “wheat”

The first 2 steps are executed as they should, the cell becomes red, and it has “upgraded” value. However, the cell color won’t change to “wheat” in step 3. I have to do:

grid.ForceRefresh()

after step 3 to get the cell color change to “wheat” color.

Could you please explain why I have to use grid.ForceRefresh() after step 3? And why didn’t I need it after step 1?

Best regards

steve wrote:

Could you please explain why I have to use grid.ForceRefresh() after
step 3? And why didn't I need it after step 1?

Probably because there was already a paint event pending.

You really should refactor your code to not interact with the GUI objects from the threads. What you've shown in your sample code may appear to be working, but it is only a happy accident. It will eventually have crashes or other bad behavior. Instead you should be executing those tasks in the UI thread, and an easy way to do it is to use the wx.CallAfter function to toss the calling of a function over to the UI thread.

···

--
Robin Dunn
Software Craftsman