Search code examples
pythoncanvaswxpythonwxwidgets

Change background color of a Canvas ScaledText


I'm using wxPython Canvas' AddScaledTextBox(...) to create a scaled Text Box.

See here for example:

Box = Canvas.AddScaledTextBox("A Two Line\nString",
                                  Point,
                                  2,
                                  BackgroundColor = "Yellow",
                                  LineColor = "Red",
                                  LineStyle = "Solid",
                                  PadSize = 5,
                                  Family = wx.TELETYPE,
                                  Position = 'bl')

How to change the Background color, later, after the textbox has been defined? (for example user input => background color change)


Solution

  • Pretty sure this is a bug. See lines 1841 - 1845 in the wxPython source - there is a reference to self.BackgroundColor but it's never used.

    So for your example, you need to set the color of the brush associated with the text box. I've based the following off of Robin Dunn's example. The function SetBoxBackground is the important part.

    As noted in the comments, just calling box.Brush.SetColour(color) or box.Pen.SetColour(color) can cause issues: if you have two text boxes with the same color, changing the brush/pen color for one will also affect the other. (I'm not 100% sure, but I think this is because of caching, see for example this comment in the source.)

    import wx
    from wx.lib.floatcanvas import FloatCanvas
    
    class TestFrame(wx.Frame):
        def __init__(self, *args, **kwargs):
            wx.Frame.__init__(self, *args, **kwargs)
            self.canvas = FloatCanvas.FloatCanvas(self, BackgroundColor = "black")
            MainSizer = wx.BoxSizer(wx.VERTICAL)
            MainSizer.Add(self.canvas, 4, wx.EXPAND)
            self.SetSizer(MainSizer)
            self.box = self.canvas.AddScaledTextBox("A Two Line\nString",
                                      (0,10),
                                      2,
                                      BackgroundColor = "Yellow",
                                      LineColor = "Red",
                                      LineStyle = "Solid",
                                      PadSize = 5,
                                      Family = wx.TELETYPE,
                                      Position = 'bl')
            self.box2 = self.canvas.AddScaledTextBox("Second Box",
                                      (0,0),
                                      2,
                                      BackgroundColor = "Yellow",
                                      LineColor = "Red",
                                      LineStyle = "Solid",
                                      PadSize = 5,
                                      Family = wx.TELETYPE,
                                      Position = 'bl')
            self.box.Bind(FloatCanvas.EVT_FC_LEFT_DOWN, self.OnRectDown)
            wx.CallAfter(self.canvas.ZoomToBB)
    
        def OnRectDown(self, event):
            print ('Rectangle: Left Button down clicked at:', event.HitCoords)
            if self.box.Color == 'red':
                self.SetBoxBackground('green', "Solid")
                self.box.SetColor('black')
            else:
                self.SetBoxBackground('white', "Solid")
                self.box.SetColor('red')
            self.canvas.ClearBackground()
            self.canvas.Refresh()
            self.canvas.Draw(True)
    
        def SetBoxBackground(self, color, style, linewidth=1):
            # See https://github.com/wxWidgets/wxPython/blob/master/wx/lib/floatcanvas/FloatCanvas.py#L1841
    
            # Create a new brush (fill) with specified color
            self.box.SetBrush(color, style)
            # Create a new pen (line) with specified color
            self.box.SetPen(color, style, linewidth)
            self.box.SetBackgroundColor(color) # Now this works correctly
    
    app = wx.App(0)
    frame = TestFrame(None, title="Test")
    frame.Show(True)
    app.MainLoop()