Ok, I got it working with a custom ArtProvider… here’s my demo:
#!/usr/bin/env python
from random import random
import wx
#import wx.aui as aui
import wx.lib.agw.aui as aui
text = """\
Hello!
Welcome to this little demo of coloring Notebook tabs dynamically using a custom AuiDefaultTabArt object.
To try it out, click tabs and another will randomly change color.
"""
#----------------------------------------------------------------------
color_whole_tab = True
class BgColorTabArt(aui.AuiDefaultTabArt):
def __init__(self):
# AuiNotebook
# clones the tab art per tab strip via AuiDefaultTabArt.Clone(), which only
# preserves attributes whose names end in _colour/_font/_brush/_pen
# (see aui_utilities.CopyAttributes).
self._custom_bg_colour = {}
super().__init__()
def SetPageBgColour(self, page_index, colour):
self._custom_bg_colour[page_index] = colour
def DrawTab(self, dc, wnd, page, rect, close_button_state, *args):
old_base = self._base_colour
try:
page_index = -1
if hasattr(wnd, "GetPageCount") and hasattr(wnd, "GetPage"):
for i in range(wnd.GetPageCount()):
if wnd.GetPage(i) == page:
page_index = i
break
if page_index in self._custom_bg_colour:
colour = self._custom_bg_colour[page_index]
if color_whole_tab:
# SetDefaultColours() recomputes ALL the derived colours that
# DrawTab() actually paints with: _base_colour_pen/_brush
# (active tab fill), _tab_top_colour/_tab_bottom_colour
# (active gradient), _tab_inactive_top_colour/
# _tab_inactive_bottom_colour (inactive gradient), and
# _border_colour/_border_pen.
self.SetDefaultColours(colour)
else:
# just underline the tab with the color:
# # Fill tab rect
btm_rect = wx.Rect(*page.rect)
btm_rect.height -= 4
btm_rect.width -= 1
btm_rect.height //= 2
btm_rect.y = btm_rect.y + page.rect.height - btm_rect.height - 1
dc.SetBrush(wx.Brush(colour))
dc.SetPen(wx.Pen(colour))
dc.DrawRectangle(btm_rect)
# Call base class with whatever args we got
return super().DrawTab(dc, wnd, page, rect, close_button_state, *args)
finally:
self.SetDefaultColours(old_base)
class TestPanel(wx.Panel):
def __init__(self, parent, log):
self.log = log
wx.Panel.__init__(self, parent, -1)
self.nb = aui.AuiNotebook(self)
self._art = BgColorTabArt()
self.nb.SetArtProvider(self._art)
page = wx.TextCtrl(self.nb, -1, text, style=wx.TE_MULTILINE)
self.nb.AddPage(page, "Welcome")
for num in range(1, 5):
page = wx.TextCtrl(self.nb, -1, "This is page %d" % num ,
style=wx.TE_MULTILINE)
self.nb.AddPage(page, "Tab Number %d" % num)
self._art.SetPageBgColour(0, wx.RED)
sizer = wx.BoxSizer()
sizer.Add(self.nb, 1, wx.EXPAND)
self.SetSizer(sizer)
self.Bind(aui.EVT_AUINOTEBOOK_PAGE_CHANGED, self.OnPageChanged)
wx.CallAfter(self.nb.SendSizeEvent)
def OnPageChanged(self, evt):
print("OnPageChanged")
import random
page_to_color = random.randint(0, self.nb.GetPageCount() - 1)
color = wx.Colour(int(random.random() * 255), int(random.random() * 255), int(random.random() * 255))
self.nb.GetArtProvider().SetPageBgColour(page_to_color, color)
evt.Skip()
#----------------------------------------------------------------------
class TestFrame(wx.Frame):
def __init__(self):
super().__init__(None, title="AuiNotebook Dynamic Tab Background Color Test", size=(800, 200))
panel = TestPanel(self, None)
sizer = wx.BoxSizer(wx.VERTICAL)
sizer.Add(panel, 1, wx.EXPAND | wx.ALL, 10)
self.SetSizer(sizer)
self.SetSize(800, 200)
class TestApp(wx.App):
def OnInit(self):
frame = TestFrame()
frame.Show()
return True
if __name__ == '__main__':
app = TestApp()
app.MainLoop()
Enjoy!