Search code examples
pythonwxpythonwxwidgets

How to make a Grid in wxPython?


I want to make a grid like this:

enter image description here

Not the wx.Grid. Does anyone know how to do this, and could provide an example?

This would be for a GridSizer or GridBagSizer to separate the widgets.


Solution

  • use the drawing context of the frame wxWindow subclass(frame/panel/etc...really any wxObject almost).

    one way of doing it is this

    import wx
    class MyCustomFrame(wx.Frame):
        def __init__(self,parent,id):
            wx.Frame.__init__(self,parent,id)
            self.Bind(wx.EVT_PAINT,self.OnPaint)
        def OnPaint(self,evt):
            self.dc = dc = wx.PaintDC(self)
            p1 = [0,0]
            p2 = [500,0]
            for i in range(100):
                dc.DrawLine(p1[0],p1[1],p2[0],p2[1])
                p1 = [p1[0],p1[1]+5]
                p2 = [p2[0],p2[1]+5]
            p1=[0,0]
            p2 = [0,500]
            for i in range(100):
                dc.DrawLine(p1[0],p1[1],p2[0],p2[1])
                p1 = [p1[0]+5,p1[1]]
                p2 = [p2[0]+5,p2[1]]
    if __name__ == "__main__":
        a = wx.App(redirect=False)
        f = MyCustomFrame(None,-1)
        #f.OnPaint(None) --- dont do this!!!
        f.Show()
        a.MainLDop()
    

    you could speed it up by using drawlines instead

        def OnPaint(self,evt):
            self.dc = dc = wx.PaintDC(self)
            verticle_lines = [(i*5,0,i*5,500) for i in range(100)]
            horizontal_lines = [(0,i*5,500,i*5) for i in range(100)]
            dc.DrawLineList(horizontal_lines+verticle_lines)
    

    In Order to do what you want with the grid sizer you could do this

    import  wx
    class   MyCustomPanel(wx.Panel):
        def __init__(self,parent,id):
            wx.Panel.__init__(self,parent,id)
            self.sz =   wx.GridSizer(5,5,0,0)
            for i   in  range(25):
                self.sz.Add(wx.StaticText(self,-1,str(i)))
            self.SetSizer(self.sz)
            self.Bind(wx.EVT_PAINT,self.OnPaint)
        def OnPaint(self,evt):
            self.dc =   dc  =   wx.PaintDC(self)
            w,h = self.sz.GetSize()
            nr = self.sz.GetRows()
            nc = self.sz.GetCols()
            cell_w = float(w)/nc
            cell_h = float(h)/nr
            hlines = [(0,i*cell_h,w,i*cell_h)for i in range(nr+1)]
            vlines = [(i*cell_w,0,i*cell_w,h)for i in range(nc+1)]
            self.dc.DrawLineList(hlines+vlines)
    
    if  __name__    ==  "__main__":
        a   =   wx.App(redirect=False)
        f1 = wx.Frame(None,-1)
        f   =   MyCustomPanel(f1,-1)
        #f.OnPaint(None)
        f1.Show()
        a.MainLoop()
    

    you could also accomplish this with styles like this

    import  wx
    class SimplePanel(wx.Panel):
        def __init__(self,parent,id,str_val):
            wx.Panel.__init__(self,parent,id,style=wx.SIMPLE_BORDER)
            self.sz = wx.BoxSizer()
            self.sz.Add(wx.StaticText(self,-1,str_val),0,wx.ALIGN_CENTER)
            self.SetSizer(self.sz)
    class   MyCustomPanel(wx.Panel):
        def __init__(self,parent,id):
    
            wx.Panel.__init__(self,parent,id)
            self.sz =   wx.GridSizer(5,5,0,0)
            for i   in  range(25):
                self.sz.Add(SimplePanel(self,-1,str(i)),0,wx.GROW)
            self.SetSizer(self.sz)
    
    if  __name__    ==  "__main__":
        a   =   wx.App(redirect=False)
        f1 = wx.Frame(None,-1)
        f   =   MyCustomPanel(f1,-1)
        #f.OnPaint(None)
        f1.Show()
        a.MainLoop()