Embedding transparent matplotlib figure canvas in wx

I have a GUI written in wxPython with a matplotlib figure embedded. I want the background color of the figure to be the same as the rest of the (quite large) GUI. Unfortunately the exact color of the GUI is OS-dependent, so it is not enough to set a fixed background color since it will change with the OS. Therefore I tried to use facecolor='none' when creating the matplotlib-figure. However that gave some unexpected problems (see image below): every time you redraw the canvas the label text and tick marks is getting thicker as if the weight of the font is changing. I found this three years old question, which seems to deal with a very similar problem, but it does not have any solution nor comments of what to do. Is this an intended feature of matplotlib/wxpython or just a bug which as not yet been fixed?

Example code to show the problem. I create two FigureCanvases, where the first one has a facecolor='b background, and with it the text is not getting thicker when redrawing the canvas. The second canvas is using facecolor='none' , and gives thicker and thicker text for each canvas redraw.

import wx
from matplotlib.figure import Figure
from matplotlib.backends.backend_wxagg import FigureCanvasWxAgg


class MyCanvas(wx.Panel):
    def __init__(self, parent, col):
        wx.Panel.__init__(self, parent, id=-1)

        self.fig = Figure(figsize=(1, 1), edgecolor='k', facecolor=col)
        self.ax = self.fig.add_subplot(1, 1, 1)
        self.ax.set_ylabel('Label')
        self.fig.subplots_adjust(left=0.5)
        self.canvas = FigureCanvasWxAgg(self, -1, self.fig)

        szr_ctr = wx.BoxSizer(wx.VERTICAL)
        szr_ctr.Add(self.canvas, 1, wx.ALL | wx.GROW)
        self.SetSizerAndFit(szr_ctr)

        wx.CallAfter(self.canvas.draw)


class wind(wx.Frame):

    def __init__(self, parent, title):
        wx.Frame.__init__(self, parent)

        self.i = 0
        figsizer = wx.BoxSizer(wx.HORIZONTAL)

        self.canvas1 = MyCanvas(self, col='b')
        figsizer.Add(self.canvas1, 1, wx.GROW | wx.ALL)

        self.canvas2 = MyCanvas(self, col='none')
        figsizer.Add(self.canvas2, 1, wx.GROW | wx.ALL)

        button = wx.Button(self, wx.ID_CLOSE, "Press me")
        button.Bind(wx.EVT_BUTTON, self.on_button)

        sizer = wx.BoxSizer(wx.VERTICAL)
        sizer.Add(figsizer, 1, wx.ALL | wx.GROW, 10)
        sizer.Add(button, 0, wx.ALL, 10)


        self.SetSizer(sizer)
        self.Layout()
        self.Show()

    def on_button(self, event):
        wx.CallAfter(self.canvas1.canvas.draw)
        wx.CallAfter(self.canvas2.canvas.draw)


if __name__ == '__main__':
    wxapp = wx.App(redirect=False)
    v = wind(None, "Fig")
    wxapp.MainLoop()

Figure with blue background works as expected. Figure with none background gets thicker and thicker texts and axes-lines after a few canvas redraws.


Edit

Changing the redraw-function to (below) solves the problem with the canvas not being properly redrawn.

def on_button(self, event):
    wx.CallAfter(self.canvas1.canvas.draw)
    wx.CallAfter(self.canvas2.canvas.draw)
    wx.CallAfter(self.canvas1.Refresh)  #  <-----------
    wx.CallAfter(self.canvas2.Refresh)  #  <-----------

After fiddling around a bit more, I realised the problem can be solved by using self.canvas_i.Refresh() after self.canvas_i.canvas.draw() . As far as I understand Refresh will mark the canvas as "in need of redrawing", forcing it to be repainted completely. This overpaints any old content and makes it just one iteration old (every new canvas.draw just draws the new thing ontop of the old, slightly placed to the side giving "thicker text").

链接地址: http://www.djcxy.com/p/37910.html

上一篇: 更改mpld3中的刻度线标签颜色

下一篇: 在wx中嵌入透明matplotlib图形画布