将matplotlib图形从绘图转换为Tkinter画布小部件嵌入的图形

将matplotlib图形从绘图转换为Tkinter画布小部件嵌入的图形,matplotlib,tkinter,embed,Matplotlib,Tkinter,Embed,我试图在Tkinter画布小部件中嵌入股价图。我有一个用matplotlib编写的功能齐全的股价图。在尝试将我的图形嵌入Tkinter时,我发现(被告知)作为绘图编写的matplotlib图形无法正确嵌入Tkinter,并且该图形必须以图形的形式嵌入才能正常工作。为了便于说明,这里是一个以绘图形式显示的matplotlib示例图 def schart20(stock_sym): x = [1,2,3,4] y = [20,21,20.5, 20.8] plt.plot(x

我试图在Tkinter画布小部件中嵌入股价图。我有一个用matplotlib编写的功能齐全的股价图。在尝试将我的图形嵌入Tkinter时,我发现(被告知)作为绘图编写的matplotlib图形无法正确嵌入Tkinter,并且该图形必须以图形的形式嵌入才能正常工作。为了便于说明,这里是一个以绘图形式显示的matplotlib示例图

def schart20(stock_sym):
    x = [1,2,3,4]
    y = [20,21,20.5, 20.8]
    plt.plot(x,y)
    plt.show()
这是同一张图,但形式是图形

def schart21(stock_sym):
    x = [1,2,3,4]
    y = [20,21,20.5, 20.8]
    fig = Figure()
    axes = fig.add_subplot(111)
    axes.plot(x,y)
    return fig
schart21代码可以成功嵌入Tkinter,但schart20代码无法。我的股价图代码是以绘图的形式显示的,我需要将其转换为图形的形式。我对matplotlib的使用经验很少,不知道如何根据需要修改代码。这是我的股票价格表代码。此代码功能齐全,但需要访问底层文件才能工作

def graphData(stock, MA1, MA2):

    try:
        stockFile = '/Users/BioASys/BioasysDB/CompanyStockPriceData/'+stock+'.txt'



        date, closep, highp, lowp, openp,volume=np.loadtxt(stockFile,delimiter=',',unpack=True,
converters={ 0: mdates.strpdate2num('%Y%m%d')})

        x = 0
        y = len(date)
        candleAr = []
        while x < y:
            appendLine = date[x], openp[x], closep[x], highp[x], lowp[x], volume[x]
            candleAr.append(appendLine)
            x+=1


        Av1 = movingaverage(closep, MA1)
        Av2 = movingaverage(closep, MA2)

        SP = len(date[MA2-1:])

        label1 = str(MA1) + ' SMA'
        label2 = str(MA2) + ' SMA'


        fig = plt.figure()


        ax1 = plt.subplot2grid((5,4),(0,0), rowspan=4, colspan=4)
        candlestick(ax1, candleAr[-SP:], width=0.6, colorup='g', colordown='r')

        ax1.plot(date[-SP:],Av1[-SP:],'#5998ff', label=label1, linewidth=1.5)
        ax1.plot(date[-SP:],Av2[-SP:],'blue', label=label2, linewidth=1.5)


        plt.ylabel('Stock price')
        ax1.grid(True)
        plt.legend(loc=3,prop={'size':7},fancybox=True,)

        ax2 = plt.subplot2grid((5,4), (4,0), sharex=ax1, rowspan=1, colspan=4)
        #ax2 = plt.subplot2grid((5,4), (4,0), rowspan=1, colspan=4)
        ax2.bar(date, volume)
        ax2.axes.yaxis.set_ticklabels([])
        plt.ylabel('Volume')
        ax2.grid(True)


        ax1.xaxis.set_major_locator(mticker.MaxNLocator(10))
        ax1.xaxis.set_major_formatter(mdates.DateFormatter('%Y-%m-%d'))




        for label in ax1.xaxis.get_ticklabels():
            label.set_rotation(90)

        for label in ax2.xaxis.get_ticklabels():
            label.set_rotation(45)


        plt.xlabel('Date')
        #plt.ylabel('Stock Price')
        plt.suptitle(stock+' Stock Price')

        plt.setp(ax1.get_xticklabels(), visible=False)

        plt.subplots_adjust(left=.09, bottom=.18, right=.94, top=.94, wspace=.20, hspace=0)

        plt.show()
        #fig.savefig('example.png') # saves a copy of the sticok chart to example.png


    except Exception, e:
        print 'failed main loop',str(e)
def图形数据(库存、MA1、MA2): 尝试: stockFile='/Users/BioASys/BioasysDB/CompanyStockPriceData/'+stock+'.txt' 日期,closep,highp,lowp,openp,volume=np.loadtxt(stockFile,分隔符=',',unpack=True, 转换器={0:mdates.strpdate2num(“%Y%m%d”)} x=0 y=len(日期) 烛光=[] 当x对于ax1.xaxis.get_ticklabels()中的标签: 标签。设置旋转(90) 对于ax2.xaxis.get_ticklabels()中的标签: 标签。设置旋转(45) plt.xlabel(“日期”) #plt.ylabel(“股价”) plt.suptitle(股票+股票价格) plt.setp(ax1.getxticklabels(),visible=False) plt.subplot_adjust(左=0.09,下=0.18,右=0.94,上=0.94,wspace=0.20,hspace=0) plt.show() #fig.savefig('example.png')#将粘贴图表的副本保存到example.png 除例外情况外,e: 打印“主循环失败”,str(e)
如果有人知道如何把这个从一个图转换成一个数字,我将非常感谢你的帮助。诚恳地说,乔治

了解Matplotlib最重要的事情之一是它以三种模式之一运行(因为没有更好的词)。1) 它在pylab中根深蒂固,2)它有一个pyplot接口,3)它有一个底层的对象接口。我会尽力解开它们,如果有任何比我更熟悉的人认为我下面所说的有任何错误,请让我知道,我会纠正它

第一种方法几乎在任何时候都应该避免——它在numpy和scipy中也会流血,永远不应该用于脚本或编码。第二个主要用于(或应该)交互式绘图,旨在模拟Matlab的功能。最后一个对于编码来说是最健壮的,并且对于您想要进行的嵌入类型是必不可少的

您的代码目前使用的是后两者的混搭,这实际上可能会导致问题-pyplot在幕后做的比只制作情节更多。Matplotlib本质上是面向对象的,pyplot只是一个巨大的包装器,它可以方便地帮助Matlab用户进行转换。它使用默认的后端进行显示(在我的情况下,大多数时候它都使用Qt4Agg),而实际上您希望强制它使用TkAgg,以便Tkinter知道如何处理它。如果你不小心的话,Pyplot可能会干扰这一点

您真正应该保留的唯一pyplot调用是figure creation
fig=plt.figure()
,以及您的
subplot2grid
调用。实际上,如果直接导入地物对象(
来自matplotlib.figure import figure
),也可以取消地物调用。拥有轴后,放弃pyplot并直接使用对象方法(即
ax.plot()
)。在线阅读了解如何使用它们,对它们的呼叫要求有时是不同的

Tkinter嵌入使用FigureCastKagg对象,这需要Figure对象。因此,plotting函数必须返回该地物对象,以便用于构造FigureCanvasTkAgg。您也不需要任何
plt.show()
——只需弹出当前的pyplot图形,而您实际上并不需要它,因为您的图形嵌入到GUI中

因此,当前问题的答案与以前相同-尽可能多地删除
plt.
命令,并
返回fig
。然后在GUI代码中可以执行以下操作

fig = graphData(stock, MA1, MA2)
canvas = FigureCanvasTkAgg(fig)
下面是一个最小的示例,它以与您类似的方式运行,没有任何错误,完全不使用pyplot

import Tkinter as Tk
import numpy as np
from matplotlib.figure import Figure
from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg

def myplotcode():
    x = np.linspace(0,2*np.pi)
    fig = Figure()
    ax = fig.add_subplot(111)
    ax.plot(x, x**2)

    return fig

class mygui(Tk.Frame):
    def __init__(self, parent):
        Tk.Frame.__init__(self, parent)
        self.parent = parent

        self.fig = myplotcode()
        self.canvas = FigureCanvasTkAgg(self.fig, master=parent)
        self.canvas.show()

        self.canvas.get_tk_widget().pack()
        self.pack(fill=Tk.BOTH, expand=1)

root = Tk.Tk()
app = mygui(root)

root.mainloop()

由于我回答了你之前的问题,我可以看出你在哪里感到困惑,我有一个澄清问题,这可能会影响我的回答。你对o有多熟悉