ramcdougal
ramcdougal

Reputation: 2367

Matplotlib and wxPython PopupMenu cooperation

I would like to display a context menu over a matplotlib figure inside of a wxPython window when the mouse is clicked.

Unfortunately, after it detects the click, the PopupMenu method is called, but it neither returns nor displays a popup. (This is with the stock Python in Ubuntu 12.10 inside of VirtualBox with a Windows 7 host.)

Here is my code so far; what am I missing? i.e. How do I get the PopupMenu to actually display?

import wx
import numpy
import matplotlib
matplotlib.use('WXAgg')
from matplotlib.figure import Figure
from matplotlib.backends.backend_wxagg import FigureCanvasWxAgg as FigCanvas
from wxPython.wx import *

class MatplotlibContext(wx.Frame):
    def __init__(self):
        wx.Frame.__init__(self, None, -1, 'some title')
        self.panel = wx.Panel(self)
        self.fig = Figure()
        self.canvas = FigCanvas(self.panel, -1, self.fig)
        self.axes = self.fig.add_subplot(111)
        x = numpy.linspace(0, 6.28)
        y = numpy.sin(x)
        self.axes.plot(x, y)
        self.canvas.draw()
        self.canvas.mpl_connect('button_press_event', self.context_menu)        
        self.vbox = wx.BoxSizer(wx.VERTICAL)
        self.vbox.Add(self.canvas, 1, wx.LEFT | wx.TOP | wx.GROW)
        self.panel.SetSizer(self.vbox)
        self.vbox.Fit(self)

    def context_menu(self, event):
        print 'in context_menu callback: clicked at (%g, %g)' % (event.x, event.y)
        menu = wxMenu()
        item_id = wxNewId()
        menu.Append(item_id, 'item') 
        wx.EVT_MENU(menu, item_id, self.callback)
        self.PopupMenu(menu, wx.Point(event.x, event.y))
        menu.Destroy()

    def callback(self, event):
        print 'menu selection: %r' % event.GetId()

app = wx.PySimpleApp()
app.frame = MatplotlibContext()
app.frame.Show()
app.MainLoop()

Edit 2013-01-31: corrected typo in the code. Revised question:

The code above doesn't work on two different machines where I ran Ubuntu 12.10 in a VirtualBox nor on a 12.04 installed directly, but mostly works on a fourth machine running 12.10. I have no idea why there's a difference.

Otherwise, I guess my question is now:

Edit 2013-10-02: version information

For one of the machines where this doesn't work, I'm running Ubuntu 13.04 with Python 2.7.4, Matplotlib 1.2.1, and wx 2.8.12.1.

Upvotes: 2

Views: 1567

Answers (1)

Astromaolagin
Astromaolagin

Reputation: 21

One thing I've found is that with some combinations of wxpython/matplotlib (not sure which ones), you can somehow lock up the event loop by showing a modal window object from a matplotlib event handler. The issue is that the matplotlib FigureCanvas doesn't release the mouse automatically, so the breakage occurs when e.g. a modal dialog tries to grab input before the mouse release event has fired.

There seems to be a simple solution, at least for the cases I've run into. Insert:

event.guiEvent.GetEventObject().ReleaseMouse()

at the start of the event handler.

Upvotes: 1

Related Questions