Auto wrap and newlines in the wxPython grid

I want to implement a grid with cells that have the following behavior:

  • cell text should be wrapped if it is not suitable for the cell

  • newlines (\ n) in the text of the cell must also be processed

i.e. the same behavior as in table editors such as MS Excel, OO Calc, etc., when you enable the "wrap words" parameter for cells.

I am trying to do it like this:

import wx 
import wx.grid 

class MyGrid(wx.grid.Grid): 

    def __init__(self, parent = None, style = wx.WANTS_CHARS): 

        wx.grid.Grid.__init__(self, parent, -1, style = style) 

        self.CreateGrid(10, 10) 

        self.editor = wx.grid.GridCellAutoWrapStringEditor() 
        self.SetDefaultEditor(self.editor)

        self.SetDefaultRenderer(wx.grid.GridCellAutoWrapStringRenderer()) 

        self.SetCellValue(0, 0, "Line1\nLine2\nLine3") 
        self.SetRowSize(0, 100) 


class MyFrame(wx.Frame): 

    def __init__(self, parent = None, title = "Multiline"): 

        wx.Frame.__init__(self, parent, -1, title) 

        self.Bind(wx.EVT_CHAR_HOOK, self.on_frame_char_hook) 

        panel = wx.Panel(self) 

        vbox = wx.BoxSizer(wx.VERTICAL) 
        panel.SetSizer(vbox) 

        grid = MyGrid(panel) 
        vbox.Add(grid, 1, wx.EXPAND | wx.ALL, 5) 
        self.grid = grid 

        btn_exit = wx.Button(panel, -1, "Exit") 
        vbox.Add(btn_exit, 0, wx.ALIGN_CENTER_HORIZONTAL | wx.ALL, 10) 

    #Proceed CTRL+ENTER as newline in the cell editor
    def on_frame_char_hook(self, event): 

        if event.CmdDown() and event.GetKeyCode() == wx.WXK_RETURN: 
            if self.grid.editor.IsCreated(): 
                self.grid.editor.StartingKey(event) 
            else: 
                event.Skip 
        else: 
            event.Skip()


if __name__ == "__main__": 
    app = wx.PySimpleApp() 
    f = MyFrame() 
    f.Center() 
    f.Show() 
    app.MainLoop()

But this code does not work as expected - new lines are processed correctly in the cell editor, but are ignored in the cell renderer. If I delete self.SetDefaultRenderer(wx.grid.GridCellAutoWrapStringRenderer()), then new lines are processed both in the editor and in the renderer, but, obviously, automatic packaging in the renderer does not work.

Does anyone know how to solve this?

+3
1

, :

from wx.lib import wordwrap
import wx.grid


class CutomGridCellAutoWrapStringRenderer(wx.grid.PyGridCellRenderer):   
    def __init__(self): 
        wx.grid.PyGridCellRenderer.__init__(self)

    def Draw(self, grid, attr, dc, rect, row, col, isSelected):
        text = grid.GetCellValue(row, col)
        dc.SetFont( attr.GetFont() ) 
        text = wordwrap.wordwrap(text, grid.GetColSize(col), dc, breakLongWords = False)
        hAlign, vAlign = attr.GetAlignment()       
        if isSelected: 
            bg = grid.GetSelectionBackground() 
            fg = grid.GetSelectionForeground() 
        else: 
            bg = attr.GetBackgroundColour()
            fg = attr.GetTextColour() 
        dc.SetTextBackground(bg) 
        dc.SetTextForeground(fg)
        dc.SetBrush(wx.Brush(bg, wx.SOLID))
        dc.SetPen(wx.TRANSPARENT_PEN)
        dc.DrawRectangleRect(rect)            
        grid.DrawTextRectangle(dc, text, rect, hAlign, vAlign)

    def GetBestSize(self, grid, attr, dc, row, col): 
        text = grid.GetCellValue(row, col)
        dc.SetFont(attr.GetFont())
        text = wordwrap.wordwrap(text, grid.GetColSize(col), dc, breakLongWords = False)
        w, h, lineHeight = dc.GetMultiLineTextExtent(text)                   
        return wx.Size(w, h)        

    def Clone(self): 
        return CutomGridCellAutoWrapStringRenderer()
+3

All Articles