W. MacTurk
W. MacTurk

Reputation: 170

wxPython - grid.AutoSizeColumns() doesn't apply to the index column?

I've got a grid of analysis results that shows up in my results frame, and after creating the grid object I call grid.AutoSizeColumns() to fit the columns to the data contents. This works fine for the actual columns containing data, but the leftmost column (the 'index' column?) containing just the row indices remains fairly wide -- much wider than needed, since there's only four rows. What I'd like to do: -Remove the leftmost column (the gray one containing only row indices), and/or -Remove the actual "Index" column (with the header "Index") as it's redundant, and narrow the leftmost gray column, OR -Remove both the leftmost column AND the column labeled "index".

Note: I am aware of the grid.DeleteCols(pos=0, numCols=1) method, but this always throws an error:

wx._core.wxAssertionError: C++ assertion ""Assert failure"" failed at ..\..\src\generic\grid.cpp(1471) in wxGridTableBase::DeleteCols(): Called grid table class function DeleteCols
but your derived table class does not override this function

and I'm not sure how to "override this function". If someone could explain the error to me/how to fix it so that grid.DeleteCols() works, that would be halfway to solving my issue (the other half being narrowing or deleting that gray far-left column in the grid)

Minimal code example below, along with a screenshot of what it currently looks like (taken from the actual program, not the minimal code)

On a related note, is there an easy way to right-justify the cell values in the grid? I format the results to all have the same number of decimal places, and I think it would look neater if the values were right-justfied (or even centered).

Minimal example:

import wx
import wx.grid
import numpy as np
import pandas as pd

class StartFrame(wx.Frame):
    def __init__(self, parent):
        wx.Frame.__init__(self, parent=parent,
         id=wx.ID_ANY, title="title", size=wx.Size(900,600),
         style=wx.CAPTION|wx.CLOSE_BOX|wx.MINIMIZE_BOX|wx.SYSTEM_MENU|wx.RESIZE_BORDER)
        self.SetSizeHints(wx.DefaultSize, wx.DefaultSize)

        self.numarray=[[1,0.0000,0.071,3.535,3.313,0.22],
                       [10,1.000,0.071,3.535,3.888,-0.353],
                       [20,1.301,0.357,4.634,4.526,0.108],
                       [50,1.699,0.929,6.456,6.442,0.023]]
        self.df = pd.DataFrame(self.numarray, columns=['Parasites/ml','log_qty',
         'probability','probit','est. probit','residual'])

        self.table = DataTable(self.df)
        grid = wx.grid.Grid(self, -1)
        grid.SetTable(self.table, takeOwnership=True)
        grid.AutoSizeColumns()

        self.pnl = wx.Panel(self)
        self.vsizer = wx.BoxSizer(wx.VERTICAL)
        self.hsizer = wx.BoxSizer(wx.HORIZONTAL)

        self.hsizer.AddStretchSpacer()
        self.hsizer.Add(grid, 0, wx.CENTER)
        self.hsizer.AddStretchSpacer()
        self.vsizer.AddStretchSpacer()
        self.vsizer.Add(self.hsizer, wx.SizerFlags().Expand().Border(wx.ALL, 5))
        self.vsizer.AddStretchSpacer()
        self.pnl.SetSizerAndFit(self.vsizer)

class DataTable(wx.grid.GridTableBase):
    def __init__(self, printdata=None):
        wx.grid.GridTableBase.__init__(self)
        self.headerRows = 1
        if printdata is None: data = pd.DataFrame()
        self.data = printdata

    def GetNumberRows(self):
        return len(self.data)

    def GetNumberCols(self):
        return len(self.data.columns) + 1

    def GetValue(self, row, col):
        if col == 0: return self.data.index[row]
        return self.data.iloc[row, col - 1]

    def SetValue(self, row, col, value):
        self.data.iloc[row, col - 1] = value

    def GetColLabelValue(self, col):
        if col == 0:
            if self.data.index.name is None: return 'Index'
            else: return self.data.index.name
        return str(self.data.columns[col - 1])

def main():
    app = wx.App()
    frm = StartFrame(None)
    frm.Show()
    app.MainLoop()

if __name__ == "__main__":
    main()

how the grid currently looks in the actual application

Upvotes: 1

Views: 501

Answers (1)

Rolf of Saxony
Rolf of Saxony

Reputation: 22443

You can Hide Columns and/or Rows, so that is an easy method of dealing with the errant left-hand column.

Hide comes in useful for other things as well e.g. grid.HideRowLabels(), will hide those pesky row numbers of the left.

The alignment issue could probably be handled by using a wx.grid.GridCellAttrProvider or you can simply iterate over the grid setting each cell, as I have done below for simplicity.

import wx
import wx.grid
import numpy as np
import pandas as pd

class StartFrame(wx.Frame):
    def __init__(self, parent):
        wx.Frame.__init__(self, parent=parent,
         id=wx.ID_ANY, title="title", size=wx.Size(900,600),
         style=wx.CAPTION|wx.CLOSE_BOX|wx.MINIMIZE_BOX|wx.SYSTEM_MENU|wx.RESIZE_BORDER)
        self.SetSizeHints(wx.DefaultSize, wx.DefaultSize)

        self.numarray=[[1,0.0000,0.071,3.535,3.313,0.22],
                       [10,1.000,0.071,3.535,3.888,-0.353],
                       [20,1.301,0.357,4.634,4.526,0.108],
                       [50,1.699,0.929,6.456,6.442,0.023]]
        self.df = pd.DataFrame(self.numarray, columns=['Parasites/ml','log_qty',
         'probability','probit','est. probit','residual'])

        self.table = DataTable(self.df)
        grid = wx.grid.Grid(self, -1)
        grid.SetTable(self.table, takeOwnership=True)
        # Hide Index column
        grid.HideCol(0)
        grid.HideRowLabels()
        # Alignment of cells
        r = grid.GetNumberRows()
        c = grid.GetNumberCols()
        for row in range(r):
            for cell in range(c):
                grid.SetCellAlignment(row, cell, wx.ALIGN_RIGHT, wx.ALIGN_CENTER)
        grid.AutoSizeColumns()
        self.pnl = wx.Panel(self)
        self.vsizer = wx.BoxSizer(wx.VERTICAL)
        self.hsizer = wx.BoxSizer(wx.HORIZONTAL)

        self.hsizer.AddStretchSpacer()
        self.hsizer.Add(grid, 0, wx.CENTER)
        self.hsizer.AddStretchSpacer()
        self.vsizer.AddStretchSpacer()
        self.vsizer.Add(self.hsizer, wx.SizerFlags().Expand().Border(wx.ALL, 5))
        self.vsizer.AddStretchSpacer()
        self.pnl.SetSizerAndFit(self.vsizer)

class DataTable(wx.grid.GridTableBase):
    def __init__(self, printdata=None):
        wx.grid.GridTableBase.__init__(self)
        self.headerRows = 1
        if printdata is None: data = pd.DataFrame()
        self.data = printdata

    def GetNumberRows(self):
        return len(self.data)

    def GetNumberCols(self):
        return len(self.data.columns) + 1

    def GetValue(self, row, col):
        if col == 0: return self.data.index[row]
        return self.data.iloc[row, col - 1]

    def SetValue(self, row, col, value):
        self.data.iloc[row, col - 1] = value

    def GetColLabelValue(self, col):
        if col == 0:
            if self.data.index.name is None: return 'Index'
            else: return self.data.index.name
        return str(self.data.columns[col - 1])

def main():
    app = wx.App()
    frm = StartFrame(None)
    frm.Show()
    app.MainLoop()

if __name__ == "__main__":
    main()

enter image description here

Upvotes: 1

Related Questions