1 ''' drawingOnGridColumnLabel.py
   2     2003-12-03
   3 
   4     This example shows a wxGrid with some sample columns, where the column
   5     headers draw sort indicators when clicked. The example does not actually
   6     do the sorting of the data, as it is intended to show how to draw on the
   7     grid's column headers.
   8 
   9     by Paul McNett (p@ulmcnett.com) and whoever wrote the GridCustTable.py demo,
  10     from which I pulled the CustomDataTable() class.
  11 
  12     I didn't know what to do until Robin pointed out an undocumented method in
  13     wxGrid: GetGridColLabelWindow(), which returns a reference to the wxWindow
  14     that makes up the column header for the grid. From there, I could trap that
  15     window's Paint event, and draw the column labels myself, including graphical
  16     sort indicators.
  17 '''
  18 
  19 from wxPython.wx import *
  20 from wxPython.grid import *
  21 
  22 class CustomDataTable(wxPyGridTableBase):
  23     """ From the wxPython demo
  24     """
  25 
  26     def __init__(self):
  27         wxPyGridTableBase.__init__(self)
  28 
  29         self.colLabels = ['ID', 'Description', 'Severity', 'Priority', 'Platform',
  30                           'Opened?', 'Fixed?', 'Tested?', 'TestFloat']
  31 
  32         self.dataTypes = [wxGRID_VALUE_NUMBER,
  33                           wxGRID_VALUE_STRING,
  34                           wxGRID_VALUE_CHOICE + ':only in a million years!,wish list,minor,normal,major,critical',
  35                           wxGRID_VALUE_NUMBER + ':1,5',
  36                           wxGRID_VALUE_CHOICE + ':all,MSW,GTK,other',
  37                           wxGRID_VALUE_BOOL,
  38                           wxGRID_VALUE_BOOL,
  39                           wxGRID_VALUE_BOOL,
  40                           wxGRID_VALUE_FLOAT + ':6,2',
  41                           ]
  42 
  43         self.data = [
  44             [1010, "The foo doesn't bar", "major", 1, 'MSW', 1, 1, 1, 1.12],
  45             [1011, "I've got a wicket in my wocket", "wish list", 2, 'other', 0, 0, 0, 1.50],
  46             [1012, "Rectangle() returns a triangle", "critical", 5, 'all', 0, 0, 0, 1.56]
  47 
  48             ]
  49 
  50 
  51     #--------------------------------------------------
  52     # required methods for the wxPyGridTableBase interface
  53 
  54     def GetNumberRows(self):
  55         return len(self.data) + 1
  56 
  57     def GetNumberCols(self):
  58         return len(self.data[0])
  59 
  60     def IsEmptyCell(self, row, col):
  61         try:
  62             return not self.data[row][col]
  63         except IndexError:
  64             return true
  65 
  66     # Get/Set values in the table.  The Python version of these
  67     # methods can handle any data-type, (as long as the Editor and
  68     # Renderer understands the type too,) not just strings as in the
  69     # C++ version.
  70     def GetValue(self, row, col):
  71         try:
  72             return self.data[row][col]
  73         except IndexError:
  74             return ''
  75 
  76     def SetValue(self, row, col, value):
  77         try:
  78             self.data[row][col] = value
  79         except IndexError:
  80             # add a new row
  81             self.data.append([''] * self.GetNumberCols())
  82             self.SetValue(row, col, value)
  83 
  84             # tell the grid we've added a row
  85             msg = wxGridTableMessage(self,                             # The table
  86                                      wxGRIDTABLE_NOTIFY_ROWS_APPENDED, # what we did to it
  87                                      1)                                # how many
  88 
  89             self.GetView().ProcessTableMessage(msg)
  90 
  91 class MyGrid(wxGrid):
  92     def __init__(self, parent):
  93 
  94         wxGrid.__init__(self, parent, -1)
  95         table = CustomDataTable()
  96         self.SetTable(table, true)
  97 
  98         self.SetRowLabelSize(0)
  99         self.SetMargins(0,0)
 100         self.AutoSizeColumns(False)
 101 
 102         # A click in the column header will set these:
 103         self.sortedColumn = -1
 104         self.sortedColumnDescending = False
 105 
 106         # trap the column label's paint event:
 107         columnLabelWindow = self.GetGridColLabelWindow()
 108         EVT_PAINT(columnLabelWindow, self.OnColumnHeaderPaint)
 109 
 110         # trap the grid label's left click:
 111         EVT_GRID_LABEL_LEFT_CLICK(self, self.OnGridLabelLeftClick)
 112 
 113     def OnColumnHeaderPaint(self, evt):
 114         w = self.GetGridColLabelWindow()
 115         dc = wxPaintDC(w)
 116         clientRect = w.GetClientRect()
 117         font = dc.GetFont()
 118         
 119         # For each column, draw it's rectangle, it's column name,
 120         # and it's sort indicator, if appropriate:
 121         #totColSize = 0
 122         totColSize = -self.GetViewStart()[0]*self.GetScrollPixelsPerUnit()[0] # Thanks Roger Binns
 123         for col in range(self.GetNumberCols()):
 124             dc.SetBrush(wxBrush("WHEAT", wxTRANSPARENT))
 125             dc.SetTextForeground(wxBLACK)
 126             colSize = self.GetColSize(col)
 127             rect = (totColSize,0,colSize,32)
 128             dc.DrawRectangle(rect[0] - (col<>0 and 1 or 0), rect[1], 
 129                              rect[2] + (col<>0 and 1 or 0), rect[3])
 130             totColSize += colSize
 131             
 132             if col == self.sortedColumn:
 133                 font.SetWeight(wxBOLD)
 134                 # draw a triangle, pointed up or down, at the
 135                 # top left of the column.
 136                 left = rect[0] + 3
 137                 top = rect[1] + 3
 138 
 139                 dc.SetBrush(wxBrush("WHEAT", wxSOLID))
 140                 if self.sortedColumnDescending:
 141                     dc.DrawPolygon([(left,top), (left+6,top), (left+3,top+4)])
 142                 else:
 143                     dc.DrawPolygon([(left+3,top), (left+6, top+4), (left, top+4)])
 144             else:
 145                 font.SetWeight(wxNORMAL)
 146 
 147             dc.SetFont(font)
 148             dc.DrawLabel("%s" % self.GetTable().colLabels[col],
 149                      rect, wxALIGN_CENTER | wxALIGN_TOP)
 150 
 151     
 152     def OnGridLabelLeftClick(self, evt):
 153         self.processSort(evt.GetCol())
 154 
 155     def processSort(self, gridCol=None):
 156         if gridCol == None:
 157             gridCol = self.GetGridCursorCol()
 158 
 159         descending = False
 160         if gridCol == self.sortedColumn:
 161             if self.sortedColumnDescending == False:
 162                 descending = True
 163         
 164         self.sortedColumn = gridCol
 165         self.sortedColumnDescending = descending
 166         self.Refresh()
 167 
 168 if __name__ == "__main__":
 169         # instantiate a simple app object:
 170         app = wxPySimpleApp()
 171         frame = wxFrame(None, -1, "Click on any column header")
 172         frame.SetSize((400,200))
 173         object = MyGrid(frame)
 174         object.SetFocus()
 175         frame.Show(1)
 176         app.MainLoop()

DrawingOnGridColumnLabel (last edited 2008-03-11 10:50:31 by localhost)

NOTE: To edit pages in this wiki you must be a member of the TrustedEditorsGroup.