Search code examples
pythonwxpythonwxwidgets

Using python's wx.grid, how can you merge columns?


Here is the table I have created so far.

enter image description here

Here is what I would like it to look like, with the columns merged.

enter image description here

I would like to merge the columns Yesterday and Today across three columns each. So Yesterday would be above Equity, Volatility, and Cash. Then likewise for Today. I have found one function called wx.grid.SetColSize(self, int col, int width), but it didn't have any effect. Does anyone know how to do this?

Here is my code as well.

import wx
import wx.grid as gridlib

class MyForm(wx.Frame):
    def __init__(self):
        """Constructor"""
        wx.Frame.__init__(self, parent=None, title="Strategies' Allocations")
        self.panel = wx.Panel(self)

        button_refresh = wx.Button(self.panel, id=wx.ID_ANY, label='Refresh')
        button_refresh.Bind(wx.EVT_BUTTON, self.refresh)

        self.myGrid1 = gridlib.Grid(self.panel)
        self.myGrid1.CreateGrid(2, 6)

        self.myGrid1.SetRowLabelSize(60)
        self.myGrid1.SetRowLabelValue(0, "")
        self.myGrid1.SetRowLabelValue(1, "ABRVXX")

        for i in range(6):
            self.myGrid1.SetColSize(i, 60)

        self.myGrid1.SetColLabelValue(0, "")
        self.myGrid1.SetColLabelValue(1, "Yesterday")
        self.myGrid1.SetColLabelValue(2, "")
        self.myGrid1.SetColLabelValue(3, "")
        self.myGrid1.SetColLabelValue(4, "Today")
        self.myGrid1.SetColLabelValue(5, "")

        self.myGrid1.SetCellValue(0, 0, "Equity")
        self.myGrid1.SetCellValue(0, 1, "Volatility")
        self.myGrid1.SetCellValue(0, 2, "Cash")
        self.myGrid1.SetCellValue(0, 3, "Equity")
        self.myGrid1.SetCellValue(0, 4, "Volatility")
        self.myGrid1.SetCellValue(0, 5, "Cash")

        self.myGrid1.SetColLabelAlignment( wx.ALIGN_CENTRE, wx.ALIGN_CENTRE )
        self.myGrid1.SetDefaultCellAlignment( wx.ALIGN_CENTRE, wx.ALIGN_TOP )
        # ******************************* #

        self.myGrid2 = gridlib.Grid(self.panel)
        self.myGrid2.CreateGrid(2, 6)

        for i in range(6):
            self.myGrid2.SetColSize(i, 60)

        self.myGrid2.SetColLabelValue(0, "")
        self.myGrid2.SetColLabelValue(1, "Yesterday")
        self.myGrid2.SetColLabelValue(2, "")
        self.myGrid2.SetColLabelValue(3, "")
        self.myGrid2.SetColLabelValue(4, "Today")
        self.myGrid2.SetColLabelValue(5, "")

        self.myGrid2.SetCellValue(0, 0, "Treasury")
        self.myGrid2.SetCellValue(0, 1, "Volatility")
        self.myGrid2.SetCellValue(0, 2, "Cash")
        self.myGrid2.SetCellValue(0, 3, "Treasury")
        self.myGrid2.SetCellValue(0, 4, "Volatility")
        self.myGrid2.SetCellValue(0, 5, "Cash")

        self.myGrid2.SetRowLabelSize(60)
        self.myGrid2.SetRowLabelValue(0, "")
        self.myGrid2.SetRowLabelValue(1, "ABRXIV")

        self.myGrid2.SetColLabelAlignment( wx.ALIGN_CENTRE, wx.ALIGN_CENTRE )
        self.myGrid2.SetDefaultCellAlignment( wx.ALIGN_CENTRE, wx.ALIGN_TOP )
        # ****************************** #

        sizer = wx.BoxSizer(wx.VERTICAL)
        sizer.Add(self.myGrid1, 1, wx.TOP|wx.ALIGN_CENTRE, 2)
        sizer.Add(self.myGrid2, 1, wx.TOP|wx.ALIGN_CENTRE, 2)
        sizer.Add(button_refresh, 1, wx.RIGHT|wx.LEFT|wx.TOP|wx.BOTTOM|wx.EXPAND|wx.ALIGN_CENTRE, 50)

        self.panel.SetSizer(sizer)
        self.panel.SetSize((500,400))
        self.SetSize((500,400))
        self.panel.Layout()

    def refresh(self, event):
        pass

if __name__ == "__main__":
    app = wx.App()
    frame = MyForm().Show()
    app.MainLoop()

Solution

  • A quick and dirty way is to dump the column labels SetColLabelSize(0) and add the headings as cells.
    Then adjust the cell spans just for those cells with SetCellSize().
    Below I have altered myGrid1 but not myGrid2.

    import wx
    import wx.grid as gridlib
    
    class MyForm(wx.Frame):
        def __init__(self):
            """Constructor"""
            wx.Frame.__init__(self, parent=None, title="Strategies' Allocations")
            self.panel = wx.Panel(self)
    
            button_refresh = wx.Button(self.panel, id=wx.ID_ANY, label='Refresh')
            button_refresh.Bind(wx.EVT_BUTTON, self.refresh)
    
            self.myGrid1 = gridlib.Grid(self.panel)
            self.myGrid1.CreateGrid(3, 6)
    
            self.myGrid1.SetRowLabelSize(80)
            self.myGrid1.SetRowLabelValue(0, "")
            self.myGrid1.SetRowLabelValue(1, "")
            self.myGrid1.SetRowLabelValue(2, "2")
    
            for i in range(6):
                self.myGrid1.SetColSize(i, 60)
    
    #        self.myGrid1.SetColLabelValue(0, "")
    #        self.myGrid1.SetColLabelValue(1, "Yesterday")
    #        self.myGrid1.SetColLabelValue(2, "")
    #        self.myGrid1.SetColLabelValue(3, "")
    #        self.myGrid1.SetColLabelValue(4, "Today")
    #        self.myGrid1.SetColLabelValue(5, "")
    
            self.myGrid1.SetColLabelSize(0)
            self.myGrid1.SetCellSize(0, 0, 1, 3)
            self.myGrid1.SetCellValue(0, 0, "Yesterday")
            self.myGrid1.SetCellSize(0, 3, 1, 3)
            self.myGrid1.SetCellValue(0, 3, "Today")
    
            self.myGrid1.SetCellValue(1, 0, "Equity")
            self.myGrid1.SetCellValue(1, 1, "Volatility")
            self.myGrid1.SetCellValue(1, 2, "Cash")
            self.myGrid1.SetCellValue(1, 3, "Equity")
            self.myGrid1.SetCellValue(1, 4, "Volatility")
            self.myGrid1.SetCellValue(1, 5, "Cash")
    
            self.myGrid1.SetColLabelAlignment( wx.ALIGN_CENTRE, wx.ALIGN_CENTRE )
            self.myGrid1.SetDefaultCellAlignment( wx.ALIGN_CENTRE, wx.ALIGN_TOP )
            # ******************************* #
    
            self.myGrid2 = gridlib.Grid(self.panel)
            self.myGrid2.CreateGrid(2, 6)
    
            for i in range(6):
                self.myGrid2.SetColSize(i, 60)
    
            self.myGrid2.SetColLabelValue(0, "")
            self.myGrid2.SetColLabelValue(1, "Yesterday")
            self.myGrid2.SetColLabelValue(2, "")
            self.myGrid2.SetColLabelValue(3, "")
            self.myGrid2.SetColLabelValue(4, "Today")
            self.myGrid2.SetColLabelValue(5, "")
    
            self.myGrid2.SetCellValue(0, 0, "Treasury")
            self.myGrid2.SetCellValue(0, 1, "Volatility")
            self.myGrid2.SetCellValue(0, 2, "Cash")
            self.myGrid2.SetCellValue(0, 3, "Treasury")
            self.myGrid2.SetCellValue(0, 4, "Volatility")
            self.myGrid2.SetCellValue(0, 5, "Cash")
    
            self.myGrid2.SetRowLabelSize(60)
            self.myGrid2.SetRowLabelValue(0, "")
            self.myGrid2.SetRowLabelValue(1, "2")
    
            self.myGrid2.SetColLabelAlignment( wx.ALIGN_CENTRE, wx.ALIGN_CENTRE )
            self.myGrid2.SetDefaultCellAlignment( wx.ALIGN_CENTRE, wx.ALIGN_TOP )
            # ****************************** #
    
            sizer = wx.BoxSizer(wx.VERTICAL)
            sizer.Add(self.myGrid1, 1, wx.TOP|wx.ALIGN_CENTRE, 2)
            sizer.Add(self.myGrid2, 1, wx.TOP|wx.ALIGN_CENTRE, 2)
            sizer.Add(button_refresh, 1, wx.RIGHT|wx.LEFT|wx.TOP|wx.BOTTOM|wx.EXPAND|wx.ALIGN_CENTRE, 50)
    
            self.panel.SetSizer(sizer)
            self.panel.SetSize((500,400))
            self.SetSize((500,400))
            self.panel.Layout()
    
        def refresh(self, event):
            pass
    
    if __name__ == "__main__":
        app = wx.App()
        frame = MyForm().Show()
        app.MainLoop()
    

    enter image description here