按钮在第二个(嵌套)图形中不起作用



我想我在Matplotlib中遇到了一个错误,尽管我真的希望它只是我缺少的一些简单的东西。

我正在编写的代码在Ubuntu 11.10、Ubuntu 12.04和MacOS上运行良好。最近我在我的机器上安装了Fedora 18,我注意到Matplotlib有一些问题:我有一个带按钮的图形。单击按钮,它会打开另一个窗口,其中也有一些按钮。在我的Fedora系统上,第二个窗口中的按钮处于非活动状态。它们不会对悬停做出响应(不会改变颜色),也不会对单击做出响应。

下面是一小段模拟这个问题的代码。这在我的Ubuntu 12.04上运行得很好,但在Fedora上不行。它的工作原理如下:显示一个有大按钮的图形,如果你点击按钮,它会显示另一个有按钮的图形。如果一切顺利,第二个按钮应该响应悬停,并在单击时向终端打印一些内容。

import pylab
from matplotlib.widgets import Button

def draw_button1(event):
    pylab.figure()
    a = pylab.axes([0.1, 0.1, 0.8, 0.8])
    b = Button(a, 'Button 1')
    def say_something(event):
        print "This works."
    b.on_clicked(say_something)
    pylab.show()
def draw_button2():
    pylab.figure()
    a = pylab.axes([0.1, 0.1, 0.8, 0.8])
    b = Button(a, 'Button 2')
    b.on_clicked(draw_button1)
    pylab.show()
draw_button2()

我不知道是什么原因造成的。我试过很多东西:

  1. 我已经从yum存储库安装了Matplitlib 1.2.0、1.2.1,以及我从源代码构建的最新1.3.0rc2。他们都这么做。我还安装了Matplotlib的所有相关依赖项,甚至是那些可选的。

  2. 我试着在我的Fedora机器上在Ubuntu 12.04上远程运行我的代码。。也许X如何渲染这些窗口有问题?仍然可以在我的Ubuntu上工作,在我的Fedora上渲染。

  3. 在这个问题上愤怒的谷歌搜索并没有起到真正的作用。人们建议使用pylab.ion()pylab.ioff()进行交互式绘图,但这也没有帮助。

如果有任何帮助的话,下面是我的Matplotlib构建:

BUILDING MATPLOTLIB
            matplotlib: yes [1.3.0rc2]
                python: yes [2.7.3 (default, Aug  9 2012, 17:23:57)  [GCC
                        4.7.1 20120720 (Red Hat 4.7.1-5)]]
              platform: yes [linux2]
REQUIRED DEPENDENCIES AND EXTENSIONS
                 numpy: yes [version 1.7.1]
              dateutil: yes [using dateutil version 1.5]
               tornado: yes [using tornado version 3.1]
             pyparsing: yes [using pyparsing version 1.5.6]
                 pycxx: yes [Couldn't import.  Using local copy.]
                libagg: yes [pkg-config information for 'libagg' could not
                        be found. Using local copy.]
              freetype: yes [version 15.0.9]
                   png: yes [version 1.5.13]
OPTIONAL SUBPACKAGES
           sample_data: yes [installing]
              toolkits: yes [installing]
                 tests: yes [using nose version 1.3.0]
OPTIONAL BACKEND EXTENSIONS
                macosx: no  [Mac OS-X only]
                qt4agg: no  [PyQt4 not found]
               gtk3agg: yes [version 3.4.6]
             gtk3cairo: yes [version 3.4.6]
                gtkagg: yes [Gtk: 2.24.18 pygtk: 2.24.0]
                 tkagg: no  [The C/C++ header for Tk (tk.h) could not be
                        found.  You may need to install the development
                        package.]
                 wxagg: no  [requires wxPython]
                   gtk: yes [Gtk: 2.24.18 pygtk: 2.24.0]
                   agg: yes [installing]
                 cairo: yes [version 1.8.10]
             windowing: no  [Microsoft Windows only]
OPTIONAL LATEX DEPENDENCIES
                dvipng: yes [version 1.14]
           ghostscript: yes [version 9.06]
                 latex: no
               pdftops: yes [version 0.20.2]

提前非常感谢!

您遇到了作用域问题。当按钮对象超出范围时,它上的所有回调都会被清除。为了使按钮工作,您需要保留对Button对象的引用。

def draw_button2():
    pylab.figure()
    a = pylab.axes([0.1, 0.1, 0.8, 0.8])
    b = Button(a, 'Button 2')
    b.on_clicked(draw_button1)
    pylab.show()
    return b
b = draw_button2()

这将使第一个按钮工作,但要使第二个按钮工作,您需要某种全局结构。实现这一点的巧妙方法是将所有这些函数封装在一个类中以跟踪它们,实现这一目标的巧妙方法则是向图形对象添加属性:

import pylab
from matplotlib.widgets import Button

def draw_button1(event):
    fig = pylab.figure()
    a = pylab.axes([0.1, 0.1, 0.8, 0.8])
    b = Button(a, 'Button 1')
    def say_something(event):
        print "This works."
    b.on_clicked(say_something)
    fig._my_btn = b
    pylab.show()
def draw_button2():
    fig = pylab.figure()
    a = pylab.axes([0.1, 0.1, 0.1, 0.1])
    b = Button(a, 'Button 2')
    b.on_clicked(draw_button1)
    pylab.show()
    fig._my_btn = b

draw_button2()

最新更新