PyGridTableBase
Tom B <[email protected]>
| Newsgroups | gmane.comp.python.wxpython.devel |
|---|---|
| Message-ID | <[email protected]> |
Posted this to the user forum but now think a wxpython developer might have better insight as there were zero replies, but lots of views.. Does anyone know of examples where gridlib.PyGridTableBase is specialized to wrap a pandas dataframe object. The dataframe brings in a lot of functionality, such as sorting. I've taken several examples and modified to use a wrapped dataframe, but the sort never works. The dataframe does get sorted but the grid display is never updated. Attached is an example where the CVSData source works (commented out), and while PandasDataSource sorts the dataframe, the display not updated. The CVXData version represents the table as a list of lists. Somewhere in the class structure there is an assumption that the table has to be a [[]], and not column data, even though you can override API's for accessing elements of the table?. Or could it be I'm not overriding the needed functions ? Any insights are appreciated -- You received this message because you are subscribed to the Google Groups "wxPython-dev" group. To unsubscribe from this group and stop receiving emails from it, send an email to [email protected]. For more options, visit https://groups.google.com/d/optout.
sample_data.csv
(text/csv, 427 B)
User ID,First Name,Last Name,Address,Phone Number,Can Call U123,Joe,Cobra,384 Knoll Street,555-555-7878,True U321,Sally,Smith,567 Kerber Lane,555-555-9293,True U728,Fred,Flinstone,3 Bedrock Lane,555-555-0001,True U134,Mary,Williams,4739 Prairie Drive,555-555-0103,True U128,Ken,Keller,574 1st Street,555-555-8888,False U689,Yuki,Morimoto,8394 Sunset Blvd,555-555-9873,True U991,Craig,Johnson,167 Beach Drive,555-555-7877,False
dataGrid.py
(text/x-python, 5.8 KB)
# Chapter 5: Data Displays and Grids
# Recipe 4: Getting started with the data grid
#
import csv
from io import StringIO
import wx
import wx.grid as gridlib
import pandas as pd
class CSVDataSource(gridlib.PyGridTableBase):
def __init__(self):
super(CSVDataSource, self).__init__()
self._data = None
self._header = None
self._readOnly = list()
self._roAttr = gridlib.GridCellAttr()
self._roAttr.SetReadOnly()
c = wx.SystemSettings.GetColour(wx.SYS_COLOUR_GRAYTEXT)
self._roAttr.TextColour = c
def LoadFile(self, fileName):
reader = csv.reader(open(fileName, 'r'))
self._data = [row for row in reader]
self._header = self._data.pop(0)
self._readOnly = list()
def GetData(self):
if not self._data:
return ""
buff = StringIO()
writer = csv.writer(buff)
writer.writerow(self._header)
writer.writerows(self._data)
return buff.getvalue()
def SetColReadOnly(self, col):
self._readOnly.append(col)
def GetAttr(self, row, col, kind):
if col in self._readOnly:
self._roAttr.IncRef()
return self._roAttr
return None
def Sort(self, col, ascending):
#self._data.sort(None, lambda data: data[col], not ascending)
self._data.sort()
def GetNumberRows(self):
return len(self._data) if self._data else 0
def GetNumberCols(self):
return len(self._header) if self._header else 0
def GetValue(self, row, col):
if not self._data:
return ""
else:
return self._data[row][col]
def SetValue(self, row, col, value):
if self._data:
self._data[row][col] = value
def GetColLabelValue(self, col):
return self._header[col] if self._header else None
class PandasDataSource(gridlib.PyGridTableBase):
def __init__(self):
super(PandasDataSource, self).__init__()
self._data = None
self._header = None
self._readOnly = list()
self._roAttr = gridlib.GridCellAttr()
self._roAttr.SetReadOnly()
c = wx.SystemSettings.GetColour(wx.SYS_COLOUR_GRAYTEXT)
self._roAttr.TextColour = c
def LoadFile(self, fileName):
self._data = pd.read_csv(fileName)
self._header = self._data.columns.tolist()
self._readOnly = list()
def GetData(self):
if self._data is None:
return ""
buff = StringIO()
writer = csv.writer(buff)
writer.writerow(self._header)
writer.writerows(self._data)
return buff.getvalue()
def SetColReadOnly(self, col):
self._readOnly.append(col)
def GetAttr(self, row, col, kind):
if col in self._readOnly:
self._roAttr.IncRef()
return self._roAttr
return None
def Sort(self, col, ascending):
#self._data.sort(None, lambda data: data[col], not ascending)
#xx.sort_values(by=[self.colnames[col]],inplace=True)
self._data.sort_values(by=[self._header[col]],inplace=True)
def GetNumberRows(self):
if self._data is None:
return 0
return len(self._data)
def GetNumberCols(self):
if self._header is None:
return 0
return len(self._header)
def GetValue(self, row, col):
if self._data is None:
return ""
else:
return self._data.get_value(row,self._header[col])
def SetValue(self, row, col, value):
if not self._data is None:
self._data.set_value(row,self._header[col], value)
def GetColLabelValue(self, col):
return self._header[col] if self._header else None
class CSVEditorGrid(gridlib.Grid):
def __init__(self, parent):
super(CSVEditorGrid, self).__init__(parent)
#self._data = CSVDataSource()
self._data = PandasDataSource()
self.SetTable(self._data)
self.Bind(gridlib.EVT_GRID_COL_SORT, self.OnSort)
def OnSort(self, event):
self._data.Sort(event.Col,
self.IsSortOrderAscending())
def LoadFile(self, fileName):
self._data.LoadFile(fileName)
self.SetTable(self._data)
self.AutoSizeColumns()
def SaveFile(self, fileName):
with open(fileName, 'w') as fileObj:
fileObj.write(self._data.GetData())
def SetColReadOnly(self, col):
self._data.SetColReadOnly(col)
#------- Sample Application ---------#
class MyFrame(wx.Frame):
def __init__(self, parent, title):
super(MyFrame, self).__init__(parent, title=title)
menub = wx.MenuBar()
fmenu = wx.Menu()
fmenu.Append(wx.ID_OPEN)
fmenu.Append(wx.ID_SAVE)
menub.Append(fmenu, "File")
self.SetMenuBar(menub)
self.CreateStatusBar()
sizer = wx.BoxSizer()
self._file = 'sample_data.csv'
self._grid = CSVEditorGrid(self)
self._grid.LoadFile(self._file)
self._grid.SetColReadOnly(0)
sizer.Add(self._grid, 1, wx.EXPAND)
self.SetSizer(sizer)
self.SetInitialSize()
self.Bind(wx.EVT_MENU, self.OnSave, id=wx.ID_SAVE)
self.Bind(wx.EVT_MENU, self.OnOpen, id=wx.ID_OPEN)
def OnOpen(self, event):
dlg = wx.FileDialog(self, "Open CSV File", wildcard="*.csv")
result = dlg.ShowModal()
if result == wx.ID_OK:
self._grid.LoadFile(dlg.Path)
dlg.Destroy()
def OnSave(self, event):
self._grid.SaveFile(self._file)
self.SetStatusText("Saved file: %s" % self._file)
class MyApp(wx.App):
def OnInit(self):
self.frame = MyFrame(None, title="Data Grid")
self.frame.Show();
return True
if __name__ == "__main__":
app = MyApp(False)
app.MainLoop()