Search code examples
wxpythonwxwidgets

How can I extend the background color of a styled line to the whole line in a wxWidget TextCtrl or StyledTextCtrl?


Using TextCtrl (in wxPython) I can set the background but it doesn't extend to the full length of the line (at least not on the GTK backend).

My code is doing more or less this:

self.txt.SetBackgroundColor(wx.WHITE)

self.txt.SetDefaultStyle(wx.TextAttr(wx.BLACK, col_green))
self.txt.AppendText("text1\n")

self.txt.SetDefaultStyle(wx.TextAttr(wx.BLACK, col_red))
self.txt.AppendText("text2\n")

What I get:

[styled text1][         ctrl bg ]
[another styled text2][ ctrl bg ]

enter image description here


What I expect:

[styled text1][         keep text1 bg ]
[another styled text2][ keep text2 bg ]

enter image description here

StyledTextCtrl seems to have a more advanced API that could potentially do this on all backends but I don't know how I would go about it.


Solution

  • StyledTextCtrl works quite differently than a TextCtrl.

    • Text in the buffer has styles.
    • Styles are simple predefined numbers from 0-31. (you can only have a max of 32 simultaneous styles within a single widget)
    • Text added gets the style 0 by default
    • Style have properties like font, background/fg, ... and also a EOLFilledproperty
    • This property controls whether the style is applied for the remainder of the line (what I need)

    So basically the initial code

    self.txt.SetBackgroundColor(wx.WHITE)
    
    self.txt.SetDefaultStyle(wx.TextAttr(wx.BLACK, col_green))
    self.txt.AppendText("text1\n")
    
    self.txt.SetDefaultStyle(wx.TextAttr(wx.BLACK, col_red))
    self.txt.AppendText("text2\n")
    

    using StyledTextCtrl becomes:

    #
    # init the styles
    #
    style_text1 = 1
    self.txt.StyleSetBackground(style_text1, col_red)
    self.txt.StyleSetEOLFilled(style_text1, True)
    
    style_text2 = 2
    self.txt.StyleSetBackground(style_text2, col_green)
    self.txt.StyleSetEOLFilled(style_text2, True)
    
    #
    # helper to append styled text
    #
    def append_text(self, text, style=None):
        start = self.txt.GetLength()
        self.txt.AppendText(text)
        nb = self.txt.GetLength() - start
        if style:
            self.txt.StartStyling(start, 31)
            self.txt.SetStyling(nb, style)
    
    # since I use a readonly widget to only display data
    # unlock the widget while we append
    self.txt.SetReadOnly(False)
    self.txt.SetEditable(True)
    
    append_text("text1\n", style_text1)
    append_text("text2\n", style_text2)
    
    # lock again
    self.txt.SetReadOnly(True)
    self.txt.SetEditable(False)