2016-10-08 5 views
1

質問がありますが、これはモジュールに関連するものではないかもしれません。Matplotlibとtkinterとの接続

以下のコードでは、matplotlibでキャンバスを作成し、それをtkinterの関連フレームに割り当てる関数更新があります。次に、マウスの位置をコンソールに出力するイベントハンドラーCursorを作成します。しかし、それはしません。しかし、メソッドの更新を削除して、モジュールの本体の中にFigure、カーソル、および接続を作成するための行を使用すると、すべてうまく動作します。

私には何が欠けていますか?私はそれがPythonの基本的な知識であると考えています。可視性と正しいインスタンスを渡すことはわかりません。

import matplotlib.pyplot as plt 
from tkinter import * 
from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg 

class Cursor (object): 
    def __init__ (self, fig): 
     self.fig = fig 
     print ("initializing") 

    def mouse_move (self, event): 
     if not event.inaxes: 
      return 
     x, y = event.xdata, event.ydata 
     print (x, y) 

    def connect (self): 
     print ("Connecting") 
     self.conmove = self.fig.canvas.mpl_connect ('motion_notify_event', self.mouse_move) 

def pyplot_f(): 
    fig = plt.figure(figsize=(6,4), dpi=100) 
    axes = fig.add_subplot (111) 
    axes.plot([1,2,3,4], [1,2,3,4]) 

    Canvas = FigureCanvasTkAgg (fig, master=frame_output) 

    canvas = Canvas.get_tk_widget() 
    canvas.grid(row=0,column=0, padx=5, pady=5, sticky="nesw") 

    return fig 

w_width = 1000 
w_height = 600 
root = Tk() 
root.resizable(0,0) 

frame_output = Frame (root, bg="", relief=SUNKEN, width=w_width*0.8, height=w_height*0.9) 
frame_output.grid(row=0, column=0, padx=20, pady=20, sticky=W+N+E+S) 
frame_input = Frame (root, bg="", relief=RAISED,width=w_width*0.2, height=w_height*0.9) 
frame_input.grid(row=0, column=1, padx=20, pady=20, sticky=W+N+E+S) 

def update(): 
    fig = pyplot_f() 
    cursor = Cursor(fig) 
    cursor.connect() 

def on_closing(): 
    print ("Exiting") 
    root.quit() 

update() 
root.protocol("WM_DELETE_WINDOW", on_closing) 
root.mainloop() 

答えて

2

あなたの問題は、可変範囲と有効期間に関するものです。

update()関数が終了すると、変数figcursorがスコープから外れます。 update()内に作成された図形オブジェクトとカーソルオブジェクトには、それを指す参照先がないため、ガベージコレクションされてしまいます。 update()関数がFigureとカーソルを正常に作成していますが、それらが再び削除されることはありません。

update()内の3行をモジュール本体に移動すると、変数figcursorはスコープ内に残り、プログラムが終了するまでガベージコレクションされません。したがって、図とカーソルは作成され、すぐにガベージコレクションされません。

この問題を解決する最も簡単な方法は、カーソルを返すupdate()機能するためのものであり、その後、モジュールスコープでそれを保つ:

def update(): 
    fig = pyplot_f() 
    cursor = Cursor(fig) 
    cursor.connect() 
    return cursor 

# ... 

cursor = update() 

これは、ガベージコレクトされてからカーソルを防ぎ、カーソルが有するように図を参照すると、図はガベージコレクションされません。

+0

ありがとうございます!しかし、それは問題を解決しません。私は、新しいレイアウトを作成する更新機能を呼び出す必要があるので、カーソルを再作成する必要があるボタンがあります。ボタンの場合、カーソルは破棄されます – EvilAnton

+0

問題は確かに範囲にあります。私はその周りに道を見つけた。私はクラスを少し変更しましたが、今度はメソッドconnectのFigureにリンクします。 __init__メソッドは空のままです(合格)。また、メインモジュールにCursorのインスタンスを作成するので、常に存在し、GCによって収集されません。 – EvilAnton

関連する問題