Ooooh, that would help me out too!
Chris
Most of the examples I've seen for grids (e.g. the ones in Chapter 5
of Robin Dunn's book) only display data in a grid. I want to allow
editing and then retrieve the edited data back when I close the grid
window. Does anyone have a small sample illustrating how to do
this?
ok, I've cobbled together a sample app that does what I want. There's an initial small window that opens up (this would be your main app window). You can check the contents of the initial database with the 'Data' button. Then you can open the grid with the 'Grid' button and edit one or more of the data-fields; if you run from a console you'll see some print-out that confirms your new data. When you press the Save-Close button in the grid, the new data gets written to the database and the grid window is closed. (instead of a Save button, you could probably just wire up an OnClose method to the EVT_CLOSE event of the grid window). Back in the main app window, if you again use the 'Data' button, you'll see the newly edited contents of the database.
The problem for me was that in both my TestFrame and DataFrame I was using self.dm = DataManager(), which gave me two separate instances of DataManager that didn't talk to each other. I needed to define a single application-level instance, dm, which would be above and outside any of the classes, so that in each class I could then reference that with self.dm = dm. I'm sure this could be improved on by someone with more Python or wxPython experience, and I welcome any suggestions. Here's the sample app (base code courtesy of Robin Dunn in Chapter 5 of 'wxPython in Action'):
#gridGenericGetData.py
import wx
import wx.grid
import generictable
import pprint
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 DataManager:
def __init__(self):
self.data = data
self.olddata = None
def SetNewData(self,newdata):
self.olddata = self.data
self.data = newdata
def GetNewData(self):
return self.data
#an instance to use app-wide, in all classes
dm = DataManager()
class SimpleGrid(wx.grid.Grid):
def __init__(self, parent, mydata):
wx.grid.Grid.__init__(self, parent, -1)
tableBase = generictable.GenericTable(data, rowLabels,
colLabels)
self.tableBase = tableBase
self.SetTable(tableBase)
class TestFrame(wx.Frame):
def __init__(self, parent):
wx.Frame.__init__(self, parent, -1, "A Grid", size=(275, 275))
self.dm = dm
grid = SimpleGrid(self,self.dm.GetNewData)
self.grid = grid
sizer = wx.BoxSizer(wx.VERTICAL)
grid.SetSize((500,len(self.dm.GetNewData())*20))
sizer.Add(grid, 0, flag=wx.EXPAND)
panel = wx.Panel(self, -1)
panel.SetSize((500,10))
sizer.Add(panel, 0)
panel = wx.Panel(self, -1)
self.addButtonBar(panel, 0)
sizer.Add(panel, 0)
sizer.Fit(panel)
#sizer2.SetMinSize((410,50))
self.SetSizer(sizer)
self.Fit()
self.Bind(wx.EVT_CLOSE, self.OnbSaveClick)
def buttonData(self):
"""define the buttons to be used in this widget"""
return (("Save-Close",self.OnbSaveClick),("Cancel",self.OnbCloseClick))
def addButtonBar(self,panel, yPos=0):
"""add a bunch of buttons"""
xPos = 0
for eachLabel, eachHandler in self.buttonData():
pos = (xPos, yPos)
button = self.addButton(panel,eachLabel,eachHandler,pos)
xPos += button.GetSize().width
def addButton(self,parent,label,handler,pos=(0,0)):
"""add a button to the button bar"""
button = wx.Button(parent, -1, label, pos)
self.Bind(wx.EVT_BUTTON, handler, button)
if label == 'Save-Close': self.bSave = button
if label == 'Cancel': self.bClose = button
return button
def OnbSaveClick(self,event):
self.bSave.SetBackgroundColour('LightBlue')
self.bSave.Refresh()
#debug: wx.MessageBox("I will save your changes","Save", wx.OK)
newdata = self.grid.tableBase.ReturnValue()
print "grid has returned this data:\n", pprint.pprint(newdata)
self.dm.SetNewData(newdata)
print "new stored data is:\n", pprint.pprint(self.dm.GetNewData())
self.Destroy()
def OnbCloseClick(self,event):
self.bClose.SetBackgroundColour('LightBlue')
self.bClose.Refresh()
self.Destroy()
def OnCloseWindow(self,event):
wx.MessageBox("Please use the Close button to close this window", "Close", wx.OK | wx.ICON_WARNING)
event.Skip()
def ReturnValue(self):
newdata = self.grid.ReturnValue()
print newdata
class DataFrame(wx.Frame):
def __init__(self, parent):
wx.Frame.__init__(self,parent, -1, "Data app")
self.frame = None
self.dm = dm
panel = wx.Panel(self, -1)
label = wx.StaticText(panel, -1, "1. Press 'Data' button to see initial data\n"
"2. Press 'Grid' to generate grid, edit some data\n"
"3. Press 'Data' again to see the changed data.")
self.sizer = wx.BoxSizer(wx.VERTICAL)
self.sizer.Add(panel, 0, wx.ALL, 5)
h = label.GetSize().height+5
self.addButtonBar(self, h)
self.SetSizer(self.sizer)
self.Fit()
def buttonData(self):
"""define the buttons to be used in this widget"""
return (("Data",self.OnbDataClick),("Grid",self.OnbGridClick),("Close",self.OnbCloseClick))
def addButtonBar(self,parent, yPos=0):
"""add a bunch of buttons"""
btns = wx.StdDialogButtonSizer()
xPos = 0
for eachLabel, eachHandler in self.buttonData():
pos = (xPos, yPos)
button = self.addButton(parent,eachLabel,eachHandler,pos)
btns.AddButton(button)
xPos += button.GetSize().width
self.SetSize((xPos,button.GetSize().height+5))
btns.Realize()
self.sizer.Add(btns, 0, wx.EXPAND|wx.ALL, 5)
def addButton(self,parent,label,handler,pos=(0,0)):
"""add a button to the button bar"""
button = wx.Button(parent, -1, label, pos)
self.Bind(wx.EVT_BUTTON, handler, button)
if label == 'Grid': self.bGrid = button
if label == 'Data': self.bData = button
if label == 'Close': self.bClose = button
return button
def OnbGridClick(self,event):
self.bGrid.SetBackgroundColour('LightBlue')
self.bGrid.Refresh()
frame = TestFrame(None)
self.frame = frame
frame.Show(True)
event.Skip()
def OnbDataClick(self,event):
self.bData.SetBackgroundColour('LightBlue')
self.bData.Refresh()
displaydata = self.dm.GetNewData()
dataList = ["%s %s" % (x[0],x[1]) for x in displaydata]
wx.MessageBox("\n".join(dataList), "Data", wx.OK)
def OnbCloseClick(self,event):
self.bClose.SetBackgroundColour('LightBlue')
self.bClose.Refresh()
self.Destroy()
if __name__ == '__main__':
app = wx.PySimpleApp()
appframe = DataFrame(None)
appframe.Show(True)
app.MainLoop()
ยทยทยท
----- Original Message ----
From: Christopher Anderson <sidewinder.asu@gmail.com>
To: wxPython-users@lists.wxwidgets.org
Sent: Sunday, December 10, 2006 11:06:53 AM
Subject: Re: [wxPython-users] sample app that returns values from grid?
On 12/8/06, Stewart Midwinter <midtoad@yahoo.com> wrote:
------------------------------------
#generictable.py
import wx
import wx.grid
import pprint
class GenericTable(wx.grid.PyGridTableBase):
def __init__(self, data, rowLabels=None, colLabels=None):
wx.grid.PyGridTableBase.__init__(self)
self.data = [list(x) for x in data]
self.rowLabels = rowLabels
self.colLabels = colLabels
def GetNumberRows(self):
return len(self.data)
def GetNumberCols(self):
return len(self.data[0])
def GetColLabelValue(self, col):
if self.colLabels:
return self.colLabels[col]
def GetRowLabelValue(self, row):
if self.rowLabels:
return self.rowLabels[row]
def IsEmptyCell(self, row, col):
return False
def GetValue(self, row, col):
return self.data[row][col]
def SetValue(self, row, col, value):
try :
self.data[row][col] = value
except IndexError :
self.data.append([''] * self.GetNumberCols())
msg = wx.grid.GridTableMessage(self, wx.grid.GRIDTABLE_NOTIFY_ROWS_APPENDED, 1)
self.GetView().ProcessTableMessage(msg)
self.data[row][col] = value
print "I'm at row %s, col %s with value %s and data:\n%s" % (row, col, value, self.data)
def ReturnValue(self):
print "I'm returning this data:\n", pprint.pprint(self.data)
return self.data
__________________________________________________
Do You Yahoo!?
Tired of spam? Yahoo! Mail has the best spam protection around