且构网

分享程序员开发的那些事...
且构网 - 分享程序员编程开发的那些事

自动换行和wxPython网格中的换行符

更新时间:2022-12-27 16:30:51

通过编写自定义渲染器解决了这个问题:

  from wx.lib import wordwrap 
import wx.grid


class CutomGridCellAutoWrapStringRenderer(wx.grid.PyGridCellRenderer):
def __init __(self):
wx.grid.PyGridCellRenderer .__ init __(self)

$ drawButton(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 = GRI d.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)
$ b $ 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)
$ b $ def Clone(self):
return CutomGridCellAutoWrapStringRenderer()


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