[wxPython] wxGrid

classic Classic list List threaded Threaded
2 messages Options
Reply | Threaded
Open this post in threaded view
|

[wxPython] wxGrid

Gary Bankston
I'm trying to create a widget that will be used for editing a python
dictionary. I'm sure there are numerous ways to do it, but it seems that
a wxGrid provides about the right basic functionality. It just needs a
little bit of adjustment.

To edit a dictionary I only need 2 columns - one for the keys, the other
for the values. The widget also needs to be resizable as its window is
resized. However wxGrid seems to leave a 'blank' area to the right past
the last column. I wanted to try to adjust it so that each column is
always exactly half the width of the widget, so I created an EVT_SIZE
handler to do this.

Problem is that this handler creates some new problems:
    1> when the grid starts up, there is a 'blemish' or odd blank area
that obscures part of the
    first several cells.

    2> the entry box where you edit a cell contents starts up with the
wrong width. Its just a very
    small square. If you adjust the width of the first column it
corrects itself until you resize the
    window again.

What am I doing wrong here? Is there a method that I should call which
would to execute the grid's default onsize functionality?

There is a 3rd but less pressing problem. adjusting the width of the
first colum tends to push the end of the 2nd column past the edge of the
widget's window. I can't find anyway to override the column adjust
method in order to correct this. Anyone have any ideas on how I can
correct this.

Of course, I might be on the wrong track completely. Perhaps a wxGrid is
the wrong way to go here. It initally seemed as if it had all the basic
functionality that I needed.

My code is attached below as well as .jpg that shows the defects I'm
trying to correct

--
  __^__
/_______\  glary
\_______/  sandstorm
   /|\
--
from wxPython.wx import *

class DictEditor( wxPanel ):
 # Edits a dict
 def __init__( self, parent, ID, dict, *va, **kw ):
  self.dict = dict

  # init ----------------------------------
  va = (self, parent, ID) + va
  apply( wxPanel.__init__, va, kw )
  self.box = wxBoxSizer( wxVERTICAL )

  # Grid  ----------------------------------
  self.grid = wxGrid( self, -1 )

  glen = len( self.dict )
  self.grid.CreateGrid( glen, 2 )
  self.grid.SetEditInPlace(true)
  self.grid.SetLabelSize( wxHORIZONTAL, 15 )
  self.grid.SetLabelSize( wxVERTICAL, 0 )
  self.grid.SetLabelValue( wxHORIZONTAL, "", 0 )
  self.grid.SetLabelValue( wxHORIZONTAL, "", 1 )
  self.grid.vscrollbar = self.grid.GetVertScrollBar()
  self.box.Add( self.grid, 1, wxEXPAND )

  EVT_SIZE( self.grid, self.OnGridSize )

  # fill the editor
  pos = 0
  for key,val in self.dict.items():
   self.grid.SetCellValue( key, pos, 0 )
   self.grid.SetCellValue( val, pos, 1 )
   pos = pos + 1
  self.grid.UpdateDimensions()
  self.grid.AdjustScrollbars()
  self.grid.Layout()

  # configure ------------------------------
  self.SetAutoLayout( TRUE )
  self.SetSizer( self.box )
  self.box.Fit( self )
  self.SetSize( wxSize( 250, 300 ) )

 def OnGridSize( self, event ):
  if self.grid.vscrollbar.IsShown():
   sbx,trash = self.grid.vscrollbar.GetSizeTuple()
   sbx = sbx / 2
  else:
   sbx = 1
  gx,gy = self.grid.GetSizeTuple()
  ax = gx/2-sbx
  self.grid.SetColumnWidth( 0, ax )
  self.grid.SetColumnWidth( 1, ax )
  self.grid.UpdateDimensions()
  self.grid.AdjustScrollbars()
  self.grid.Layout()
  self.grid.Refresh()

if __name__ == '__main__':
 testdict1 = {  'Board Name': 'Insane Black Box',
         'Xetel PWB number': 'XEX0000',
         'Xetel PWB Rev Level': 'A',
         'Xetel CCA number': 'CCA0000',
         'Xetel CCA Rev Level': 'A',
         'Customer Name': 'WhackO Corp.',
         'Customer PWB number': 'x?abc?',
         'Customer PWB Rev Level': '*-_#',
         'Customer CCA number': '123-glop',
         'Customer CCA Rev Level': '+',
         'Project Type': 'Pads',
         'Status': 'fab-release' }

 testdict2 = { 'name': 'black box',
        'Description': 'crazy mixed up mess',
        'Xetel PWB number': 'XEX3243',
        'Xetel PWB Rev Level': 'A',
        'Xetel CCA number': 'XEX2339',
        'Xetel CCA Rev Level': 'gary',
        'Customer Name': 'Cricket',
        'Customer PWB Rev Level': '',
        'Customer CCA number': '',
        'Customer CCA Rev Level': '',
        'SCH Designer': 'them',
        'CAD system': 'Puds',
        'SCH system': 'illogic',
        'start date': 'yesterday',
        'completion date': '' }

 class TestFrame( wxFrame ):
  def __init__( self, parent, ID ):
   wxFrame.__init__( self, parent, ID, "DistList Editor Test Frame" )
   boxx = wxBoxSizer( wxVERTICAL )

   box1 = wxBoxSizer( wxHORIZONTAL )
   boxx.Add( box1, 1, wxEXPAND )

   # editors ---
   editor1 = DictEditor( self, -1, testdict1 )
   box1.Add( editor1, 1, wxEXPAND | wxALL, 10 )

   editor2 = DictEditor( self, -1, testdict2 )
   box1.Add( editor2, 1, wxEXPAND | wxALL, 10 )

   # configure ---
   self.SetAutoLayout( TRUE ) # tell frame to use sizer
   self.SetSizer( boxx )
   boxx.Fit( self )

 class MyApp(wxApp):
  def __init__( self  ):
   wxApp.__init__( self )

  def OnInit(self):
   self.frame = TestFrame( NULL, -1 )
   self.frame.Show( true )
   self.SetTopWindow( self.frame )
   return true

 app = MyApp(  )
 app.MainLoop()


grid.JPG (64K) Download Attachment
Reply | Threaded
Open this post in threaded view
|

Re: [wxPython] wxGrid

Robin Dunn
> Problem is that this handler creates some new problems:
>     1> when the grid starts up, there is a 'blemish' or odd blank area
> that obscures part of the
>     first several cells.
>

It's the wxTextCrl used for the in place edit, (IPE.)  Apparently when the
frame sizers move things around and you resize columns, the IPE control
doesn't get moved.  The fix is to disable IPE and then enable it again
causing it's location to be recalculated.

>     2> the entry box where you edit a cell contents starts up with the
> wrong width. Its just a very
>     small square. If you adjust the width of the first column it
> corrects itself until you resize the
>     window again.
>

You provided the panel with an EVT_SIZE where you adjust the size of the
columns.  However the default EVT_SIZE handler for the panel would have
called self.Layout() to take care of the sizer.  The wxGrid was never getting
size events and so it was never resizing it's top edit control.  You can
either call self.Layout to add in the functionality you overrode, or call
event.Skip so the default handler gets called.  Your call to self.grid.Layout
had no effect because the grid itself doesn't have any sizers or layout
constraints.


Here are my changes:

    def OnGridSize( self, event ):
        if self.grid.vscrollbar.IsShown():
            sbx,trash = self.grid.vscrollbar.GetSizeTuple()
            sbx = sbx / 2
        else:
            sbx = 1
        gx,gy = self.grid.GetSizeTuple()
        ax = gx/2-sbx
        self.grid.SetColumnWidth( 0, ax )
        self.grid.SetColumnWidth( 1, ax )
        self.grid.UpdateDimensions()
        self.grid.AdjustScrollbars()
        self.grid.SetEditInPlace(false)  ## here
        self.grid.Refresh()
        self.grid.SetEditInPlace(true)   ## here
        event.Skip()                     ## and here

--
Robin Dunn
Software Craftsman
[hidden email]
http://AllDunn.com/robin/
http://AllDunn.com/wxPython/  Check it out!



_______________________________________________
wxPython-users maillist  -  [hidden email]
http://starship.python.net/mailman/listinfo/wxpython-users