Question

I have a matplotlib graph (a FigureCanvasWxAgg object) and I’d like to place a WX Button on top of the canvas—in HTML/CSS terms, the button should have a higher z index. This initialization

button = wx.Button(canvas, label='Some Button')
button.Raise()

does the trick up until the graph redraws itself, at which point the button disappears. I can still click the button at this point, and resizing the window (which resizes the canvas) makes the button visible again. What’s the conventional way to make sure that a child window is consistently drawn above its parent?

Was it helpful?

Solution

In the backend file backend_wx.py you can see that matplotlib draws directly onto the window, and over the button you created before. What you have to do is to replace the draw method with one that triggers a redraw for the button after it drew the graph:

fig = figure()
but = Button(fig.canvas, label="button")
original_draw = fig.canvas.draw
def draw(gc=None):
    original_draw(gc)
    but.SetLabel(but.GetLabel())
fig.canvas.draw = draw
plot([1],[1])

I use but.SetLabel(but.GetLabel()) to force a redraw of the button. Sending an apropriate paint event using wx.PostEvent should work as well. If you have more than one control and don't want to draw over all of them, since resizing solves the problem, you could use SendSizeEvent() to trigger a redraw. You'll have to add some mechanism to prevent an infinite loop then, because the size event handler calls draw again.

The best solution is probably to write an own matplotlib backend, one which does not draw into the main window but into a canvas child, such that the GUI toolkit can handle the drawing order. But that's also the most involved solution. The documentation has some information on that topic, and you might also find the already mentioned backend_wx.py helpful.

By the way: If the button does not need to be on top of the canvas, you can also add it to the toolbar through gcf().canvas.toolbar.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top