开发者

Auto wrap and newlines in wxPython grid

开发者 https://www.devze.com 2023-03-02 17:19 出处:网络
I want to implement a grid with the cells that have the following behaviour: cell text should be wrapped if it doesn\'t fit to the cell

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

  1. cell text should be wrapped if it doesn't fit to the cell

  2. newlines (\n) in the cell text should be processed as well

i.e. the same behaviour as in table editors like MS Excel, OO Calc, etc. when you enable the 'wrap words' option for cells.

I'm trying to do this as follows:

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 doesn't work as expected - newlines processed correctly in the cell editor, but ignored in the cell renderer. If I remove the self.SetDefaultRenderer(wx.grid.GridCellAutoWrapStringRenderer()) then newlines processed correctly both in the editor and renderer, but obviously auto wrapping in the renderer doesn't work.

Does anybody know how to solve this?


Solved this problem by writing a custom renderer:

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()


For column headers, I was able to insert a \n (newline).

self.m_grid1.SetColLabelValue(8, "Reference \n Level")
0

精彩评论

暂无评论...
验证码 换一张
取 消

关注公众号