I cannot make new values show in a grid cell, even though ForceRefresh() is called.

Hi Raffaello,

Sorry it took me awhile to create a demo of my post of 2008.08.17: “I cannot make new values show in a grid cell, even though ForceRefresh() is called.” as requested.

Below is the program, with the ‘offending’ function:

def OnGridCellChange(self, evt):
    row,col = evt.GetRow(),evt.GetCol()
    old_val = self.grid.GetTable().GetValue(row,col)
    new = self.grid.__dict__["changed_val"]
    self.grid.SetCellValue(row,col,new_val)
    self.grid.ForceRefresh()
    new_val = self.grid.GetTable().GetValue(row,col)
    print "row==",row,";col==",col,";old_val==",old_val,";new_val==",new_val,";new==",new

Where the print line demonstrate that the value is changed, but the grid itself is not updated on the screen (in spite of self.grid.ForceRefresh()).

Any suggestions would be welcome.

Bye,

Ron.

···

#!/usr/bin/env python

import wx
import wx.grid
import string

data = ((“Bob”, “Dernier”), (“Ryne”, “Sandberg”),
(“Gary”, “Matthews”), (“Leon”, “Durham”),
(“Keith”, “Moreland”), (“Ron”, “Cey”),
(“Jody”, “Davis”), (“Larry”, “Bowa”),
(“Rick”, “Sutcliffe”))

colLabels = (“Last”, “First”)
rowLabels = (“CF”, “2B”, “LF”, “1B”, “RF”, “3B”, “C”, “SS”, “P”)

class SimpleGrid(wx.grid.Grid):
def init(self, parent):
wx.grid.Grid.init(self, parent, -1)
tableBase = GenericTable(data, rowLabels, colLabels)
self.SetTable(tableBase)

class TestFrame(wx.Frame):
def init(self, parent):
wx.Frame.init(self, parent, -1, “ForceRefresh() working ?”,
size=(275, 275))
self.grid = SimpleGrid(self)
self.BindTableEvents()
self.grid.SetDefaultEditor(UpCaseCellEditor())
self.grid.AutoSize()

def OnGridCellChange(self, evt):
    row,col = evt.GetRow(),evt.GetCol()
    old_val = self.grid.GetTable().GetValue(row,col)
    new = self.grid.__dict__["changed_val"]
    self.grid.SetCellValue(row,col,new_val)
    self.grid.ForceRefresh()
    new_val = self.grid.GetTable().GetValue(row,col)
    print "row==",row,";col==",col,";old_val==",old_val,";new_val==",new_val,";new==",new

def BindTableEvents(self):
    self.Bind(event=wx.grid.EVT_GRID_CELL_CHANGE, handler=self.OnGridCellChange, source=None)

def SetDefaultCellEditor(self,grid):
    self.editor = grid.SetDefaultEditor(grid_editor.UpCaseCellEditor())

class UpCaseCellEditor(wx.grid.PyGridCellEditor):
def init(self):
wx.grid.PyGridCellEditor.init(self)

def Create(self, parent, id, evtHandler):
    self._tc = wx.TextCtrl(parent, id, "")
    self._tc.SetInsertionPoint(0)
    self.SetControl(self._tc)

    if evtHandler:
        self._tc.PushEventHandler(evtHandler)

    self._tc.Bind(wx.EVT_CHAR, self.OnChar)

def SetSize(self, rect):
    self._tc.SetDimensions(rect.x, rect.y, rect.width+2, rect.height+2,
                           wx.SIZE_ALLOW_MINUS_ONE)

def BeginEdit(self, row, col, grid):
    self.startValue = grid.GetTable().GetValue(row, col)
    self._tc.SetValue(self.startValue)
    self._tc.SetInsertionPointEnd()
    self._tc.SetFocus()
    self._tc.SetSelection(0, self._tc.GetLastPosition())

def EndEdit(self, row, col, grid):
    changed = False

    val = self._tc.GetValue()
   
    if val != self.startValue:
        changed = True
        grid.GetTable().SetValue(row, col, val)
        """
        The contents of 'val', could be retrieved from outside
        as: self.grid.__dict__["changed_val"]
        """
        grid.changed_val = val

    self.startValue = ''
    self._tc.SetValue('')

    return changed

def Reset(self):
    self._tc.SetValue(self.startValue)
    self._tc.SetInsertionPointEnd()

def Clone(self):
    return UpCaseCellEditor()

def StartingKey(self, evt):
    self.OnChar(evt)
    if evt.GetSkipped():
        self._tc.EmulateKeyPress(evt)

def OnChar(self, evt):
    key = evt.GetKeyCode()
    if key > 255:
        evt.Skip()
        return
    char = chr(key)
    if char in string.letters:
        char = char.upper()
        self._tc.WriteText(char)
    else:
        evt.Skip()

class GenericTable(wx.grid.PyGridTableBase):

def __init__(self, data, rowLabels=None, colLabels=None):
    wx.grid.PyGridTableBase.__init__(self)
    self.data = data
    self.rowLabels = rowLabels
    self.colLabels = colLabels
   
def GetNumberRows(self):
    try:
        return len(self.data)
    except (TypeError):
        pass

def GetNumberCols(self):
    try:
        return len(self.data[0])
    except:
        pass

def GetColLabelValue(self, col):
    if self.colLabels:
        return self.colLabels[col] 

def IsEmptyCell(self, row, col):
    return False 

def GetValue(self, row, col):
    try:
        return self.data[row][col]
    except:
        pass

def SetValue(self, row, col, value):
    pass        

if name == ‘main’:
app = wx.PySimpleApp()
frame = TestFrame(None)
frame.Show(True)
app.MainLoop()

You just misplaced a line, the function should read
def OnGridCellChange(self, evt):
row,col = evt.GetRow(),evt.GetCol()
old_val = self.grid.GetTable().GetValue(row,col)
**new_val = self.grid.GetTable().GetValue(**row,col)

    new = self.grid.__dict__["changed_val"]
    self.grid.SetCellValue(row,col,new_val)
    self.grid.ForceRefresh()
   
    print "row==",row,";col==",col,";old_val==",old_val,";new_val==",new_val,";new==",new

I wonder why the stdout did not tell you that. I received at once the following error message:

C:/Python25/pythonw.exe -u “C:/Python_programs/Guests/GridNotWorking.py”
Traceback (most recent call last):
File “C:/Python_programs/Guests/GridNotWorking.py”, line 37, in OnGridCellChange

self.grid.SetCellValue(row,col,new_val)

UnboundLocalError: local variable ‘new_val’ referenced before assignment

So long

···

2008/8/20 Barak, Ron Ron.Barak@lsi.com

Hi Raffaello,

Sorry it took me awhile to create a demo of my post of 2008.08.17: “I cannot make new values show in a grid cell, even though ForceRefresh() is called.” as requested.

Below is the program, with the ‘offending’ function:

def OnGridCellChange(self, evt):
    row,col = evt.GetRow(),evt.GetCol()
    old_val = self.grid.GetTable().GetValue(row,col)
    new = self.grid.__dict__["changed_val"]
    self.grid.SetCellValue(row,col,new_val)
    self.grid.ForceRefresh()
    new_val = self.grid.GetTable().GetValue(row,col)
    print "row==",row,";col==",col,";old_val==",old_val,";new_val==",new_val,";new==",new

Where the print line demonstrate that the value is changed, but the grid itself is not updated on the screen (in spite of self.grid.ForceRefresh()).

Any suggestions would be welcome.

Bye,

Ron.


#!/usr/bin/env python

import wx
import wx.grid
import string

data = ((“Bob”, “Dernier”), (“Ryne”, “Sandberg”),
(“Gary”, “Matthews”), (“Leon”, “Durham”),
(“Keith”, “Moreland”), (“Ron”, “Cey”),
(“Jody”, “Davis”), (“Larry”, “Bowa”),
(“Rick”, “Sutcliffe”))

colLabels = (“Last”, “First”)
rowLabels = (“CF”, “2B”, “LF”, “1B”, “RF”, “3B”, “C”, “SS”, “P”)

class SimpleGrid(wx.grid.Grid):
def init(self, parent):
wx.grid.Grid.init(self, parent, -1)
tableBase = GenericTable(data, rowLabels, colLabels)
self.SetTable(tableBase)

class TestFrame(wx.Frame):
def init(self, parent):
wx.Frame.init(self, parent, -1, “ForceRefresh() working ?”,
size=(275, 275))
self.grid = SimpleGrid(self)
self.BindTableEvents()
self.grid.SetDefaultEditor(UpCaseCellEditor())
self.grid.AutoSize()

def OnGridCellChange(self, evt):
    row,col = evt.GetRow(),evt.GetCol()
    old_val = self.grid.GetTable().GetValue(row,col)
    new = self.grid.__dict__["changed_val"]
    self.grid.SetCellValue(row,col,new_val)
    self.grid.ForceRefresh()
    new_val = self.grid.GetTable().GetValue(row,col)
    print "row==",row,";col==",col,";old_val==",old_val,";new_val==",new_val,";new==",new
def BindTableEvents(self):
    self.Bind(event=wx.grid.EVT_GRID_CELL_CHANGE, handler=self.OnGridCellChange, source=None)
def SetDefaultCellEditor(self,grid):
    self.editor = grid.SetDefaultEditor(grid_editor.UpCaseCellEditor())

class UpCaseCellEditor(wx.grid.PyGridCellEditor):
def init(self):
wx.grid.PyGridCellEditor.init(self)

def Create(self, parent, id, evtHandler):
    self._tc = wx.TextCtrl(parent, id, "")
    self._tc.SetInsertionPoint(0)
    self.SetControl(self._tc)
    if evtHandler:
        self._tc.PushEventHandler(evtHandler)
    self._tc.Bind(wx.EVT_CHAR, self.OnChar)
def SetSize(self, rect):
    self._tc.SetDimensions(rect.x, rect.y, rect.width+2, rect.height+2,
                           wx.SIZE_ALLOW_MINUS_ONE)
def BeginEdit(self, row, col, grid):
    self.startValue = grid.GetTable().GetValue(row, col)
    self._tc.SetValue(self.startValue)
    self._tc.SetInsertionPointEnd()
    self._tc.SetFocus()
    self._tc.SetSelection(0, self._tc.GetLastPosition())
def EndEdit(self, row, col, grid):
    changed = False
    val = self._tc.GetValue()
   
    if val != self.startValue:
        changed = True
        grid.GetTable().SetValue(row, col, val)
        """
        The contents of 'val', could be retrieved from outside
        as: self.grid.__dict__["changed_val"]
        """
        grid.changed_val = val
    self.startValue = ''
    self._tc.SetValue('')
    return changed
def Reset(self):
    self._tc.SetValue(self.startValue)
    self._tc.SetInsertionPointEnd()
def Clone(self):
    return UpCaseCellEditor()
def StartingKey(self, evt):
    self.OnChar(evt)
    if evt.GetSkipped():
        self._tc.EmulateKeyPress(evt)
def OnChar(self, evt):
    key = evt.GetKeyCode()
    if key > 255:
        evt.Skip()
        return
    char = chr(key)
    if char in string.letters:
        char = char.upper()
        self._tc.WriteText(char)
    else:
        evt.Skip()

class GenericTable(wx.grid.PyGridTableBase):

def __init__(self, data, rowLabels=None, colLabels=None):
    wx.grid.PyGridTableBase.__init__(self)
    self.data = data
    self.rowLabels = rowLabels
    self.colLabels = colLabels
   
def GetNumberRows(self):
    try:
        return len(self.data)
    except (TypeError):
        pass
def GetNumberCols(self):
    try:
        return len(self.data[0])
    except:
        pass
def GetColLabelValue(self, col):
    if self.colLabels:
        return self.colLabels[col] 
def IsEmptyCell(self, row, col):
    return False 
def GetValue(self, row, col):
    try:
        return self.data[row][col]
    except:
        pass
def SetValue(self, row, col, value):
    pass        

if name == ‘main’:
app = wx.PySimpleApp()
frame = TestFrame(None)
frame.Show(True)
app.MainLoop()


wxpython-users mailing list

wxpython-users@lists.wxwidgets.org

http://lists.wxwidgets.org/mailman/listinfo/wxpython-users

Working on your code a bit shown me a possible origin to your problems: In the GenericTable class, the method SetValue gets called when you are finished editing, to update the underlying data, so it cannot be simply empty. At the same time, the data you are showing must be in a writable form (the tuple of tuples cannot be updated, but if you use a list of lists, it works ok). In that circumstances, neither the SetCellValue nor the ForceRefresh calls are necessary.

By the way, when you were calling SetCellValue, you were passing new_val as data, which still haven’t been defined. I just assume it was a typo while you mean to pass new.

Attached goes the modified version of your program.

Hope it helps.

Regards,

Walter

module1.py (4.66 KB)

···

El mié, 20-08-2008 a las 09:59 +0100, Barak, Ron escribió:

Hi Raffaello,
Sorry it took me awhile to create a demo of my post of 2008.08.17: “I cannot make new values show in a grid cell, even though ForceRefresh() is called.” as requested.