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

时间:2013-06-23 08:14:42

标签: python button matplotlib fedora

我想我在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()进行交互式绘图,但这也无济于事。

  4. 如果它有任何帮助,这是我的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]
    

    非常感谢!

1 个答案:

答案 0 :(得分: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()

这将使您的第一个按钮工作,但要使第二个按钮工作,您将需要某种全局结构。执行此操作的最佳方法是将所有这些函数包装在一个类中以跟踪它们,执行此操作的hacky方法是向图形对象添加属性:

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