2013-06-23 40 views
1

我想我遇到了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] 

提前感謝非常感謝!

回答

2

您遇到了範圍界定問題。當按鈕對象超出範圍時,所有的回調都會被清除。要使按鈕正常工作,您需要保留對物體周圍的物體的引用。

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

謝謝!這確實修復了它!所以真的在我的其他系統上運行得不好...... – Diana

+0

再一次,每當我想我在某個庫中發現一個錯誤時,就會發現錯誤。 :) – Diana

+0

@Diana你讀過按鈕的例子嗎? (http://matplotlib.org/examples/widgets/buttons.html)如果是這樣,我會提交一個PR來說明這一點很重要。至於爲什麼它可以在任何地方工作,有一些變化是回調在前一段時間的工作方式(改變 - >弱點),但我不確定最終發佈版本的結果。 – tacaswell