使用matplotlib的ginput功能和tkinter GUI

时间:2014-09-26 16:48:20

标签: python matplotlib tkinter ginput

我使用tkinter在python中构建了一个简单的matplotlib绘图GUI。现在我想通过ginput从图中获取坐标。不幸的是,我一直收到以下错误:

AttributeError: 'FigureCanvasTkAgg' object has no attribute 'manager'
Figure.show works only for figures managed by pyplot, normally created by pyplot.figure().

似乎ginput对tkinter不起作用,如果我不使用tkinter并且只是从命令行生成一个绘图窗口,我可以使这段代码正常工作。

我知道有一种替代方法可以使用matplotlib中的事件选择函数来完成这类事情,但我似乎无法翻译我见过的关于此功能的示例。任何人都可以告诉我这个吗?

import numpy as np
from matplotlib.pyplot import *
from Tkinter import *
from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg, NavigationToolbar2TkAgg


class App:

    def __init__(self, master):

        global frame
        frame = Frame(master)
        frame.pack(side=TOP)   

        self.quitbutton = Button(frame, text="QUIT", fg="red", command=frame.quit)
        self.quitbutton.grid(row=4,column=0,sticky=W)       

        self.hi_there = Button(frame, text="LOAD",command=self.loadfile)
        self.hi_there.grid(row=0,column=0,sticky=W)   

        self.cutbutton = Button(frame, text="CUT", fg="purple",command=self.cut)
        self.cutbutton.grid(row=1,column=0,sticky=W)        

        global canvas, ax, f

        f = Figure(figsize=(20,4))
        ax = f.add_subplot(111)
        ax.set_xlabel('Time(s)',fontsize=20)
        ax.set_ylabel('Current(nA)',fontsize=20)
        canvas = FigureCanvasTkAgg(f, master=root)
        canvas.show()
        canvas.get_tk_widget().pack(side=BOTTOM, fill=BOTH, expand=1)

        toolbar1 = NavigationToolbar2TkAgg( canvas, root )
        toolbar1.update()
        f.tight_layout()


    def loadfile(self):
        ax.clear()
        self.data=rand(1000)
        self.t=np.arange(0,len(self.data))       
        ##############################################plot data
        self.baseline=np.median(self.data)  
        self.var=2*std(self.data)
        ax.plot(self.t,self.data,'b')

        ax.set_xlabel('Time(s)',fontsize=20)
        ax.set_ylabel('Current(nA)',fontsize=20)
        ax.axhline(linewidth=2, y=self.baseline, color='g')
        ax.set_xlabel('Time(s)',fontsize=20)
        ax.set_ylabel('Current(nA)',fontsize=20)
        canvas.draw()

    def cut(self): 
        pts=np.array(f.ginput(2))
        pts=pts[:,0]
        print pts
        self.data=np.delete(self.data,pts)

        ax.clear()
        self.baseline=np.median(self.data)    
        self.t=np.arange(0,len(self.data))
        ax.plot(self.t,self.data,'b')
        ax.axhline(linewidth=2, y=self.baseline, color='g')
        canvas.draw()




root = Tk()

app = App(root)

root.mainloop()
root.destroy()

编辑:似乎问题在于图和图之间的区别

ginput似乎适用于figure()但不适用于Figure()。并且tkinter仅适用于图...

有解决方法吗?

2 个答案:

答案 0 :(得分:1)

进入python/Tkinter .mainloop() 后,将 Tkinter GUI输入基于鼠标点击事件,而不是MATLAB/pyplot .ginput()

没有严肃的控制系统(而且Tkinter .mainloop()是一个非常严重的控制系统)喜欢将它的控制缰绳移交给任何其他竞争(==阻塞)子系统。

经测试可以使用:

class App( Frame ):                                          # The user interface:

    def __init__( self, master = None ):

        Frame.__init__( self, master )
        self.fig        = Figure( ( 6, 6 ), dpi = 100 )    
        canvas          = FigureCanvasTkAgg( self.fig, master = self )
        # ---------------------------------------------------# cover Tk.root
        self.bind(                     "<Button-1>",         # Tk Event type
                                       self.showXY_handler   #    handler 2 call
                                       )
        # ----------------------------------------------------------------------
        canvas.get_tk_widget().grid(   row        = 0,       # this adds a plot
                                       column     = 0,       # on Tk.root .grid()
                                       columnspan = 4        # geometry manager
                                       )
        # ---------------------------------------------------cover graph area
        canvas.get_tk_widget().bind(   "<Button-1>",
                                       self.showXY_handler
                                       )
        # -----------------------------------------------------------


     #FINALLY THE INTERFACE TO A DEMO-HANDLER METHOD:
     def showXY_handler( self,  aHandledEVENT ):
         print aHandledEVENT.x, aHandledEVENT.y

您也可以使用Class实例变量而不是global - s

# global canvas, ax, f                  # rather to be avoided use of global-s
self.canvas =                           # instance variables, Class-wide visible  
self.ax     =
self.f      =

答案 1 :(得分:0)

正如我所知,使用from module import *这样的语法对于python来说并不是一个好习惯。最好导入全名。

此外,您还没有randstd的导入。我想,最好不要在你的情况下使用global变量。可能不是rand(1000),而是np.random.rand(1000)

您可以尝试另一种方式与MATLAB接口,例如pyqt 我尝试过我的项目。

我想,这个matplotlib的问题可以帮助你mpl gitgub。但你应该像matplotlib.use('tkagg')一样添加smth。