0

我使用 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()

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

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

有解决方法吗?

4

2 回答 2

2

进入python/Tkinter .mainloop()后,将您的TkinterGUI 输入基于鼠标单击事件,而不是基于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      =
于 2014-09-26T21:04:03.853 回答
0

据我所知,使用这样的语法from module import *对于 python 来说不是很好的做法。最好导入全名。

而且你也没有randand的进口std。我想,global在你的情况下最好不要使用变量。可能不是rand(1000),但是np.random.rand(1000)

您可以尝试另一种与 MATLAB 交互的方式,例如我在项目中尝试过的pyqt 。

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

于 2014-09-26T20:35:20.577 回答