[wxPython-users] Grid Resize overrides layout?
Mike Driscoll
mdriscoll at co.marshall.ia.us
Tue Sep 4 09:26:40 PDT 2007
> -----Original Message-----
> From: Robin Dunn [mailto:robin at alldunn.com]
> Sent: Saturday, September 01, 2007 7:58 PM
> To: wxPython-users at lists.wxwidgets.org
> Subject: Re: [wxPython-users] Grid Resize overrides layout?
>
> Mike Driscoll wrote:
> > Hi,
> >
> > I have a grid control that I'm using for what amounts to a
> spreadsheet.
> > Since some older folks will be using it, I thought I'd try
> to add the
> > ability to change the font size. Alas, I seem to be doing
> something wrong.
> > Currently, my proof of concept code is below:
> >
> > def onChangeFont(self, event):
> > font = wx.Font(12, wx.SWISS, wx.NORMAL, wx.BOLD)
> > self.sheet.SetCellFont(0,0,font)
> > self.sheet.AutoSize()
> > self.panel.Layout()
> >
> > The AutoSize command works great, although I wish I it would only
> > resize certain columns or rows rather than all of them.
>
> There are AutoSizeRow and AutoSizeColumn methods.
>
AutoSizeColumn will work for my situation. Sorry I missed that.
>
> > My problem though is that
> > after it "autosizes", some buttons I have below the grid widget are
> > pushed "off" the edge of my panel and I have to resize the panel to
> > see them again. As I understand it, all I need to do is
> call Layout,
> > but it doesn't work.
> >
> > In this case, my app is derived from a Frame object, so
> "self" is a frame.
> > I tried calling Layout in the following two ways:
> >
> > self.Layout() and self.panel.Layout()
>
> If you can produce a small sample we can help better. It
> should work as you say, but there could be something about
> the window/sizer hierarchy that is short-circuiting the layout.
>
>
> --
> Robin Dunn
> Software Craftsman
> http://wxPython.org Java give you jitters? Relax with wxPython!
>
>
>
I would still like to know why the Layout() command doesn't work though.
I've created a sample script that illustrates the problem. When you click
the button, it changes the font size in cell (0,0) to 12 point Swiss, bold
and then calls the AutoSize function and then the Layout function. This
will then cause the grid to change shape slightly and "push" the button
off the edge of the panel. If you resize the panel with your mouse, the
button reappears.
It should be noted that I am using a slightly modified version of the
SimpleGrid from the demo for my "spreadsheet". To reiterate, I am using
wxPython 2.8.4 and Python 2.4 on Windows XP SP2.
Thanks for any pointers!
Mike
-------------- next part --------------
import wx
import wx.grid as gridlib
from ts_grid import SimpleGrid
class Worksheet(wx.Frame):
def __init__(self):
wx.Frame.__init__(self, None, -1, title='Timesheet')
self.panel = wx.Panel(self, -1)
self.sheet = SimpleGrid(self.panel)
self.fontChgBtn = wx.Button(self.panel, -1, 'Change Font Size', size=(100,-1))
self.Bind(wx.EVT_BUTTON, self.onFontChange, self.fontChgBtn)
mainSizer = wx.BoxSizer(wx.VERTICAL)
mainSizer.Add(self.sheet, 0, wx.EXPAND|wx.ALL, 5)
mainSizer.Add(self.fontChgBtn, 0, wx.ALL|wx.ALIGN_CENTER_HORIZONTAL, 5)
self.panel.SetSizer(mainSizer)
mainSizer.Fit(self)
mainSizer.SetSizeHints(self)
self.Show(True)
def onFontChange(self, event):
font = wx.Font(12, wx.SWISS, wx.NORMAL, wx.BOLD)
self.sheet.SetCellFont(0,0,font)
self.sheet.AutoSize()
self.panel.Layout()
###### Run script! ######
if __name__ == '__main__':
app = wx.PySimpleApp()
Worksheet().Show() # '4' is a test userid number only
app.MainLoop()
-------------- next part --------------
import wx
import wx.grid as gridlib
class SimpleGrid(gridlib.Grid):
def __init__(self, parent):
gridlib.Grid.__init__(self, parent, wx.ID_ANY)
self.moveTo = None
self.Bind(wx.EVT_IDLE, self.OnIdle)
# Create the sheet (y,x)
self.CreateGrid(17, 12)#, gridlib.Grid.SelectRows)
##self.EnableEditing(False)
# Name the column positions with variable names
dateCol = 0
dayCol = 1
regCol = 2
otCol = 3
ceCol = 4
holCol = 5
sklvCol = 6
vacCol = 7
ctCol = 8
convCol = 9
miscCol = 10
commCol = 11
self.SetColLabelValue(dateCol, "DATE")
self.SetColLabelValue(dayCol, "DAY")
self.SetColLabelValue(regCol, "REG")
self.SetColFormatFloat(regCol, 2, 2)
self.SetColLabelValue(otCol, "OT")
self.SetColFormatFloat(otCol, 2, 2)
self.SetColLabelValue(ceCol, "CE")
self.SetColFormatFloat(ceCol, 2, 2)
self.SetColLabelValue(holCol, "HOL")
self.SetColFormatFloat(holCol, 2, 2)
self.SetColLabelValue(sklvCol, "SKLV")
self.SetColFormatFloat(sklvCol, 2, 2)
self.SetColLabelValue(vacCol, "VAC")
self.SetColFormatFloat(vacCol, 2, 2)
self.SetColLabelValue(ctCol, "CT")
self.SetColFormatFloat(ctCol, 2, 2)
self.SetColLabelValue(convCol, "CONV")
self.SetColFormatFloat(convCol, 2, 2)
self.SetColLabelValue(miscCol, "MISC")
self.SetColFormatFloat(miscCol, 2, 2)
self.SetColLabelValue(commCol, "COMMENTS")
self.SetColFormatFloat(commCol, 2, 2)
for i in range(1,11):
self.SetColSize(i,50)
self.SetColSize(11,200)
self.SetReadOnly(0,0,True)
self.SetReadOnly(0,1,True)
self.SetReadOnly(7,0,True)
self.SetReadOnly(15,0,True)
self.SetReadOnly(16,0,True)
############################################################################3
# Gray the total rows
attr = gridlib.GridCellAttr()
attr.SetTextColour(wx.BLACK)
attr.SetBackgroundColour('Light Gray')
self.SetRowAttr(7, attr)
self.SetRowAttr(15, attr)
self.SetRowAttr(16, attr)
self.SetCellValue(7,dateCol,'Week 1 Total')
self.SetCellSize(7,dateCol,1,2)
self.SetCellAlignment(7,dateCol,wx.ALIGN_CENTRE,wx.ALIGN_CENTRE)
self.SetCellFont(7,dateCol,wx.Font(10, wx.DEFAULT, wx.NORMAL, wx.BOLD))
self.SetCellValue(15,dateCol,'Week 2 Total')
self.SetCellSize(15,dateCol,1,2)
self.SetCellAlignment(15,dateCol,wx.ALIGN_CENTRE,wx.ALIGN_CENTRE)
self.SetCellFont(15,dateCol,wx.Font(10, wx.DEFAULT, wx.NORMAL, wx.BOLD))
self.SetCellValue(16,dateCol,'Grand Total')
self.SetCellSize(16,dateCol,1,2)
self.SetCellAlignment(16,dateCol,wx.ALIGN_CENTRE,wx.ALIGN_CENTRE)
self.SetCellFont(16,dateCol,wx.Font(10, wx.DEFAULT, wx.NORMAL, wx.BOLD))
# Set defaults for the Total rows
totals = [7,15,16]
for n in totals:
x = 1
for i in range(9):
x = x+1
self.SetCellValue(n,x,'0.00')
self.SetCellAlignment(n,x,wx.ALIGN_RIGHT, wx.ALIGN_RIGHT)
# set all float number rows and columns to use floats and block text
for rows in range(17):
for cols in range(11):
self.SetCellEditor(rows, cols, gridlib.GridCellFloatEditor())
self.SetColLabelAlignment(wx.ALIGN_LEFT, wx.ALIGN_BOTTOM)
# test all the events
self.Bind(gridlib.EVT_GRID_CELL_LEFT_CLICK, self.OnCellLeftClick)
self.Bind(gridlib.EVT_GRID_CELL_RIGHT_CLICK, self.OnCellRightClick)
self.Bind(gridlib.EVT_GRID_CELL_LEFT_DCLICK, self.OnCellLeftDClick)
self.Bind(gridlib.EVT_GRID_CELL_RIGHT_DCLICK, self.OnCellRightDClick)
self.Bind(gridlib.EVT_GRID_LABEL_LEFT_CLICK, self.OnLabelLeftClick)
self.Bind(gridlib.EVT_GRID_LABEL_RIGHT_CLICK, self.OnLabelRightClick)
self.Bind(gridlib.EVT_GRID_LABEL_LEFT_DCLICK, self.OnLabelLeftDClick)
self.Bind(gridlib.EVT_GRID_LABEL_RIGHT_DCLICK, self.OnLabelRightDClick)
self.Bind(gridlib.EVT_GRID_ROW_SIZE, self.OnRowSize)
self.Bind(gridlib.EVT_GRID_COL_SIZE, self.OnColSize)
self.Bind(gridlib.EVT_GRID_RANGE_SELECT, self.OnRangeSelect)
self.Bind(gridlib.EVT_GRID_CELL_CHANGE, self.OnCellChange)
self.Bind(gridlib.EVT_GRID_SELECT_CELL, self.OnSelectCell)
self.Bind(gridlib.EVT_GRID_EDITOR_SHOWN, self.OnEditorShown)
self.Bind(gridlib.EVT_GRID_EDITOR_HIDDEN, self.OnEditorHidden)
self.Bind(gridlib.EVT_GRID_EDITOR_CREATED, self.OnEditorCreated)
def OnCellLeftClick(self, evt):
evt.Skip()
def OnCellRightClick(self, evt):
evt.Skip()
def OnCellLeftDClick(self, evt):
evt.Skip()
def OnCellRightDClick(self, evt):
evt.Skip()
def OnLabelLeftClick(self, evt):
evt.Skip()
def OnLabelRightClick(self, evt):
evt.Skip()
def OnLabelLeftDClick(self, evt):
## self.log.write("OnLabelLeftDClick: (%d,%d) %s\n" %
## (evt.GetRow(), evt.GetCol(), evt.GetPosition()))
evt.Skip()
def OnLabelRightDClick(self, evt):
evt.Skip()
def OnRowSize(self, evt):
evt.Skip()
def OnColSize(self, evt):
evt.Skip()
def OnRangeSelect(self, evt):
evt.Skip()
def OnCellChange(self, evt):
'''
Show how to stay in a cell that has bad data. We can't just
call SetGridCursor here since we are nested inside one so it
won't have any effect. Instead, set coordinates to move to in
idle time.
'''
#value = self.GetCellValue(evt.GetRow(), evt.GetCol())
colNum = evt.GetCol() # Get column number to calculate which total to update
self.totalColumns(colNum)
def totalColumns(self, colNum):
# Totals the columns in the grid
if colNum != 11:
# List of cells for the 1st week's pay
tempLst = [self.GetCellValue(0,colNum), self.GetCellValue(1,colNum), self.GetCellValue(2,colNum),
self.GetCellValue(3,colNum), self.GetCellValue(4,colNum), self.GetCellValue(5,colNum),
self.GetCellValue(6,colNum)]
# List of cells for the 2nd week's pay
tempLst2 = [self.GetCellValue(8,colNum), self.GetCellValue(9,colNum), self.GetCellValue(10,colNum),
self.GetCellValue(11,colNum), self.GetCellValue(12,colNum), self.GetCellValue(13,colNum),
self.GetCellValue(14,colNum)]
# Put both lists in another list
colLists = [tempLst, tempLst2]
totRow = [7, 15] # Row numbers of the totals
i = 0 # iterator / counter
# Iterate over each list
for eachCol in colLists:
numLst = []
total = 0
for eachCell in eachCol:
if eachCell == '': # If cell is empty, add zero
numLst.append(0)
else: # else, add whatever number is in the cell
numLst.append(eachCell)
for eachNum in numLst:
total = total + float(eachNum)
self.SetCellValue(totRow[i],colNum, str(total))
i += 1
# Total the 2 week's totals to get the "Grand Total"
gTotal = float(self.GetCellValue(7,colNum)) + float(self.GetCellValue(15,colNum))
self.SetCellValue(16,colNum, str(gTotal))
def OnIdle(self, evt):
if self.moveTo != None:
self.SetGridCursor(self.moveTo[0], self.moveTo[1])
self.moveTo = None
evt.Skip()
def OnSelectCell(self, evt):
## self.log.write("OnSelectCell: (%d,%d) %s\n" %
## (evt.GetRow(), evt.GetCol(), evt.GetPosition()))
# Another way to stay in a cell that has a bad value...
row = self.GetGridCursorRow()
col = self.GetGridCursorCol()
if self.IsCellEditControlEnabled():
self.HideCellEditControl()
self.DisableCellEditControl()
value = self.GetCellValue(row, col)
if value == 'no good 2':
return # cancels the cell selection
evt.Skip()
def OnEditorShown(self, evt):
## if evt.GetRow() == 6 and evt.GetCol() == 3 and \
## wx.MessageBox("Are you sure you wish to edit this cell?",
## "Checking", wx.YES_NO) == wx.NO:
## evt.Veto()
## return
evt.Skip()
def OnEditorHidden(self, evt):
## if evt.GetRow() == 6 and evt.GetCol() == 3 and \
## wx.MessageBox("Are you sure you wish to finish editing this cell?",
## "Checking", wx.YES_NO) == wx.NO:
## evt.Veto()
## return
evt.Skip()
def OnEditorCreated(self, evt):
pass
More information about the wxpython-users
mailing list