我想我在 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()
我不知道是什么原因造成的。我尝试了很多方法:
我已经从 yum 存储库安装了 Matplitlib 1.2.0、1.2.1,以及我从源代码构建的最新 1.3.0rc2。他们都做同样的事情。我还安装了 Matplotlib 的所有相关依赖项,甚至是那些可选的依赖项。
我尝试从我的 Fedora 机器在 Ubuntu 12.04 上远程运行我的代码。也许 X 呈现这些窗口的方式存在问题?仍然可以在我的 Ubuntu 上运行,在我的 Fedora 上呈现。
对这个问题进行了激烈的谷歌搜索,但并没有真正帮助。人们建议使用
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()
关于python - 按钮在第二个(嵌套)图中不起作用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17258858/