Skip to main content
 首页 » 编程设计

python之Matplotlib 与 wxPython PopupMenu 的合作

2025年05月04日13sxdcgaq8080

我想在单击鼠标时在 wxPython 窗口内的 matplotlib 图形上显示上下文菜单。

不幸的是,在它检测到点击后,调用了 PopupMenu 方法,但它既不返回也不显示弹出窗口。 (这是在带有 Windows 7 主机的 VirtualBox 中的 Ubuntu 12.10 中的库存 Python。)

到目前为止,这是我的代码;我错过了什么?即如何让 PopupMenu 实际显示?

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() 

编辑 2013-01-31:更正了代码中的拼写错误。修改后的问题:

上面的代码不适用于我在 VirtualBox 中运行 Ubuntu 12.10 的两台不同机器,也不适用于直接安装的 12.04,但主要适用于运行 12.10 的第四台机器。我不知道为什么会有差异。

否则,我想我现在的问题是:

  • 如何解决上/下坐标问题? (如果我点击距窗口顶部一定距离,它会显示距底部的距离。)
  • 如果我打开一个 PopupMenu(并可选择关闭它),则进程不会在主窗口关闭时终止。我该如何解决这个问题?

编辑2013-10-02:版本信息

对于其中一台不起作用的机器,我正在运行 Ubuntu 13.04 和 Python 2.7.4、Matplotlib 1.2.1 和 wx 2.8.12.1。

请您参考如下方法:

我发现的一件事是,使用 wxpython/matplotlib 的某些组合(不确定是哪些),您可以通过显示来自 matplotlib 事件处理程序的模态窗口对象以某种方式锁定事件循环。问题是 matplotlib FigureCanvas 不会自动释放鼠标,因此会在例如模态对话框尝试在鼠标释放事件触发之前获取输入。

似乎有一个简单的解决方案,至少对于我遇到的情况而言。插入:

event.guiEvent.GetEventObject().ReleaseMouse() 

在事件处理程序的开头。