2015-07-21 6 views
1

Я пишу программу, которая обрабатывает некоторые данные и показывает результат как график. Я привязал сюжет к холсту, чтобы его можно было показать в том же окне Tkinter вместо того, чтобы отображаться в новом. Я хочу, чтобы фигура отображалась в отдельном окне, когда пользователь нажимает ее, используя mpl_connect. Однако он работает только один раз. Если я нажимаю холст во второй раз, ничего не происходит. Я также попытался сделать кнопку и связать событие с ней, но та же проблема возникает: она работает только один раз.Событие Canvas работает только один раз

Может кто-нибудь скажет мне, какую ошибку я делаю и как ее исправить?

import matplotlib 
matplotlib.use('TkAgg') 
import numpy as np 
from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg 
from matplotlib.figure import Figure 
import matplotlib.pyplot as plt 
from Tkinter import * 

class mclass: 
    def __init__(self, window): 
     self.window = window 
     self.leftframe= Frame (self.window) 
     self.rightframe= Frame (self.window) 
     self.leftframe.pack (side= LEFT, anchor=N) 
     self.rightframe.pack (side=RIGHT, anchor=N) 

     self.box = Entry(self.leftframe) 
     self.button = Button (self.leftframe, text="check", command=self.plot) 
     self.plotlabel= Label (self.leftframe, text="The following is the plot") 
     self.box.grid (row=1, column=1) 
     self.button.grid(row=2, column= 1) 
     self.plotlabel.grid (row=3, column=1) 

    def plot (self): 
     x=np.array ([1, 2, 3, 4, 5, 6, 7, 8, 9, 10]) 
     v= np.array ([16,16.31925,17.6394,16.003,17.2861,17.3131,19.1259,18.9694,22.0003,22.81226]) 
     p= np.array ([16.23697,  17.31653,  17.22094,  17.68631,  17.73641 , 18.6368, 
      19.32125,  19.31756 , 21.20247 , 22.41444 , 22.11718 , 22.12453]) 

     fig = plt.figure(figsize=(6,6)) 
     a = fig.add_subplot(111) 
     a.scatter(v,x,color='red') 
     a.plot(p, range(2 +max(x)),color='blue') 
     a.invert_yaxis() 

     a.set_title ("Estimation Grid", fontsize=16) 
     a.set_ylabel("Y", fontsize=14) 
     a.set_xlabel("X", fontsize=14) 

     canvas = FigureCanvasTkAgg(fig, master=self.rightframe) 
     canvas.get_tk_widget().grid(row=1, column= 2) 
     canvas.draw() 
     cid= fig.canvas.mpl_connect('button_press_event', lambda event: plt.show()) 

window= Tk() 
start= mclass (window) 
window.mainloop() 
+1

Подозреваю, что у вас проблемы с глобальным состоянием, присущим 'pyplot'. Я бы избегал использования 'pyplot' + embedding практически во всех расходах. – tacaswell

ответ

2

Как @tcaswell отметил, что при вложении, вы не можете использовать plt.figure или plt.show.

Причина, по которой вы получаете только один щелчок, заключается в том, что вы вызываете plt.show() в обратном вызове «на клик». plt.show() попытается запустить другой Tk mainloop внутри mainloop вашего приложения, блокируя все в процессе.

Также вы создаете два canvas es и прикрепляете их к одному и тому же рисунку.

plt.figure() создает фигуру, холст и фигурный менеджер, затем регистрирует их с глобальным состоянием pyplot. Вы только хотите, чтобы одна из этих вещей произошла, поэтому вы должны позвонить fig = matplotlib.figure.Figure(...). (Или в случае Figure, так как это, как вы импортировали ее)


Хорошая новость заключается в том, что это две строки исправить. Измените plt.figure(...) на Figure(...) и не вызывайте plt.show() в свой клик.

+0

Большое спасибо Джо, что я могу назвать вместо plt.show? – Dania

+1

'plt.show()' эквивалентно вашему 'window.mainloop()'. Это не то, что имеет смысл вызвать внутри нажатия кнопки callbackback. Что вы хотите сделать, чтобы сделать обратный вызов? –

+0

Спасибо, холст, который уже отображается в главном окне приложения, при нажатии на него я хочу, чтобы он отображался в отдельном окне, например, plt.show показывает рисунок в отдельном окне, которое может быть максимизировано и сведено к минимуму пользователем. Как я могу это сделать? Благодарю. – Dania

Смежные вопросы