pythonwxpythonwxformbuilderwxgrid

How do I read / update a wxgrid in a form I've created with wxFormBuilder


I have created a frame with wxFormBuilder called MyFrame1 in a .py file called gui.py. I'm trying to read and write values to that grid but have been stuck for hours trying to solve the problem. This is a simplified version of the code as the previous example I posted was overcomplicated.

The app is started in maingridtest.py and I'm trying to read and write to the grid from there. If I intergrate everything into one file (wFormBuilder gui and maingridtest into say 'code.py' I can read and write to grid no problem. I want the formbulider code kept separate to simplify updates to the gui.

No mater what I try I cant get python to find m_grid1 in gui.py.

Here is maingridtest.py

    __author__ = 'Paul'

import wx
import wx.xrc
import wx.grid
from gui import MyFrame1


class ReadGrid(MyFrame1):
    def __init__(self, parent):
        MyFrame1.__init__(self, parent)

    test = m_grid1.GetCellValue(2, 2)
    print test


if __name__ == '__main__':
    app = wx.App(0)
    MainApp = MyFrame1(None)
    MainApp.Show()
    app.MainLoop()

and here is the gui.py

# -*- coding: utf-8 -*- 

###########################################################################
## Python code generated with wxFormBuilder (version Jun 17 2015)
## http://www.wxformbuilder.org/
##
## PLEASE DO "NOT" EDIT THIS FILE!
###########################################################################

import wx
import wx.xrc
import wx.grid

ID_ABOUT = 1000

###########################################################################
## Class MyFrame1
###########################################################################

class MyFrame1 ( wx.Frame ):

    def __init__( self, parent ):
        wx.Frame.__init__ ( self, parent, id = wx.ID_ANY, title = u"Grid Test", pos = wx.DefaultPosition, size = wx.Size( 818,525 ), style = wx.CAPTION|wx.CLOSE_BOX|wx.DEFAULT_FRAME_STYLE|wx.SYSTEM_MENU|wx.TAB_TRAVERSAL )

        self.SetSizeHintsSz( wx.DefaultSize, wx.DefaultSize )

        bSizer1 = wx.BoxSizer( wx.VERTICAL )

        self.m_grid1 = wx.grid.Grid( self, wx.ID_ANY, wx.DefaultPosition, wx.DefaultSize, 0 )

        # Grid
        self.m_grid1.CreateGrid( 5, 5 )
        self.m_grid1.EnableEditing( True )
        self.m_grid1.EnableGridLines( True )
        self.m_grid1.EnableDragGridSize( False )
        self.m_grid1.SetMargins( 0, 0 )

        # Columns
        self.m_grid1.EnableDragColMove( False )
        self.m_grid1.EnableDragColSize( True )
        self.m_grid1.SetColLabelSize( 30 )
        self.m_grid1.SetColLabelAlignment( wx.ALIGN_CENTRE, wx.ALIGN_CENTRE )

        # Rows
        self.m_grid1.EnableDragRowSize( True )
        self.m_grid1.SetRowLabelSize( 80 )
        self.m_grid1.SetRowLabelAlignment( wx.ALIGN_CENTRE, wx.ALIGN_CENTRE )

        # Label Appearance

        # Cell Defaults
        self.m_grid1.SetDefaultCellAlignment( wx.ALIGN_LEFT, wx.ALIGN_TOP )
        bSizer1.Add( self.m_grid1, 0, wx.ALL, 5 )


        self.SetSizer( bSizer1 )
        self.Layout()
        self.m_menubar1 = wx.MenuBar( 0 )
        self.file = wx.Menu()
        self.m_menubar1.Append( self.file, u"File" ) 

        self.help = wx.Menu()
        self.about = wx.MenuItem( self.help, ID_ABOUT, u"About", wx.EmptyString, wx.ITEM_NORMAL )
        self.help.AppendItem( self.about )

        self.m_menubar1.Append( self.help, u"Help" ) 

        self.SetMenuBar( self.m_menubar1 )


        self.Centre( wx.BOTH )

        # Connect Events
        self.Bind( wx.EVT_CLOSE, self.closeGridFrame )

    def __del__( self ):
        pass


    # Virtual event handlers, overide them in your derived class
    def closeGridFrame( self, event ):
        event.Skip()

Solution

  • You just need to change a couple of minor things:

    import wx
    import wx.xrc
    import wx.grid
    from gui import MyFrame1
    
    
    class ReadGrid(MyFrame1):
        def __init__(self, parent):
            MyFrame1.__init__(self, parent)
    
    
            test = self.m_grid1.GetCellValue(2, 2)
            print test
    
    
    if __name__ == '__main__':
        app = wx.App(0)
        MainApp = ReadGrid(None)
        MainApp.Show()
        app.MainLoop()
    

    First of all, you need to actually call your subclass, ReadGrid, instead of MyFrame. That won't work at all. Next you want to access m_grid1 by calling it like this:

    test = self.m_grid1.GetCellValue(2, 2)
    

    Since you don't set a value in that cell, this will just return an empty string, so you still won't get any output. So I edited your gui.py code so it has a button that you can use to get that value:

    import wx
    import wx.xrc
    import wx.grid
    
    ID_ABOUT = 1000
    
    ###########################################################################
    ## Class MyFrame1
    ###########################################################################
    
    class MyFrame1 ( wx.Frame ):
    
        def __init__( self, parent ):
            style = wx.CAPTION|wx.CLOSE_BOX|wx.DEFAULT_FRAME_STYLE|wx.SYSTEM_MENU|wx.TAB_TRAVERSAL
            wx.Frame.__init__ ( self, parent, id = wx.ID_ANY, title = u"Grid Test",
                                pos = wx.DefaultPosition, size = wx.Size( 818,525 ),
                                style = style )
            panel = wx.Panel(self)
    
            #self.SetSizeHintsSz( wx.DefaultSize, wx.DefaultSize )
    
            bSizer1 = wx.BoxSizer( wx.VERTICAL )
    
            self.m_grid1 = wx.grid.Grid( panel, wx.ID_ANY, wx.DefaultPosition, wx.DefaultSize, 0 )
    
            # Grid
            self.m_grid1.CreateGrid( 5, 5 )
            self.m_grid1.EnableEditing( True )
            self.m_grid1.EnableGridLines( True )
            self.m_grid1.EnableDragGridSize( False )
            self.m_grid1.SetMargins( 0, 0 )
    
            # Columns
            self.m_grid1.EnableDragColMove( False )
            self.m_grid1.EnableDragColSize( True )
            self.m_grid1.SetColLabelSize( 30 )
            self.m_grid1.SetColLabelAlignment( wx.ALIGN_CENTRE, wx.ALIGN_CENTRE )
    
            # Rows
            self.m_grid1.EnableDragRowSize( True )
            self.m_grid1.SetRowLabelSize( 80 )
            self.m_grid1.SetRowLabelAlignment( wx.ALIGN_CENTRE, wx.ALIGN_CENTRE )
    
            # Label Appearance
    
            # Cell Defaults
            self.m_grid1.SetDefaultCellAlignment( wx.ALIGN_LEFT, wx.ALIGN_TOP )
            bSizer1.Add( self.m_grid1, 0, wx.ALL, 5 )
    
            # get a value from the grid
            value_btn = wx.Button(panel, label='Get Value')
            value_btn.Bind(wx.EVT_BUTTON, self.onGetValue)
            bSizer1.Add(value_btn, 0, wx.ALL, 5)
    
    
            panel.SetSizer( bSizer1 )
            self.Layout()
            self.m_menubar1 = wx.MenuBar( 0 )
            self.file = wx.Menu()
            self.m_menubar1.Append( self.file, u"File" )
    
            self.help = wx.Menu()
            self.about = wx.MenuItem( self.help, ID_ABOUT, u"About", wx.EmptyString, wx.ITEM_NORMAL )
            self.help.AppendItem( self.about )
    
            self.m_menubar1.Append( self.help, u"Help" )
    
            self.SetMenuBar( self.m_menubar1 )
    
    
            self.Centre( wx.BOTH )
    
            # Connect Events
            self.Bind( wx.EVT_CLOSE, self.closeGridFrame )
    
        def __del__( self ):
            pass
    
    
        # Virtual event handlers, overide them in your derived class
        def closeGridFrame( self, event ):
            event.Skip()
    
        def onGetValue(self, event):
            value = self.m_grid1.GetCellValue(2, 2)
            print value
    

    I also set the widget's parent to an instance of a wx.Panel as that is the recommended parent for most widgets. By doing that, you will get the proper look on each platform and it also gives you the ability to tab between widgets correctly.