【问题标题】:Python: How to embed matplotlib in Tkinter correctly? [closed]Python:如何在 Tkinter 中正确嵌入 matplotlib? [关闭]
【发布时间】:2018-10-15 03:31:40
【问题描述】:

提前感谢您的宝贵帮助! 我无法在 tkinter 中嵌入 matplotlib。你能指导我吗?

我已经导入了所有正确的模块 matplotlib.pyplot、matplotlib.dates、FigureCanvasTkAgg、NavigationToolbar2Tk、key_press_handler、Figure等。

然后……

root = tk.Tk()
root.wm_title("Embedding in Tk")

def bytespdate2num(fmt, encoding ='utf-8'):
    strconverter = mdates.strpdate2num(fmt)
    def bytesconverter(b):
        s = b.decode(encoding)
        return strconverter(s)
    return bytesconverter 

def graph_data(stock):
    fig = plt.figure()
    ax1 = plt.subplot2grid((1,1), (0,0))
    url_stock = 'https://pythonprogramming.net/yahoo_finance_replacement'
    source_code = urllib.request.urlopen(url_stock).read().decode()
    stock_data = []
    source_split = source_code.split('\n')

    for line in source_split[1:]:
        line_split = line.split(',')
        if len(line_split) == 7:
            if 'values' not in line and 'labels' not in line:
                stock_data.append(line)
    date, closep, highp, lowp, openp, adj_closep, volume = np.loadtxt(stock_data, delimiter =',', unpack= True, converters={0: bytespdate2num('%Y-%m-%d')})

    ax1.plot_date(date, closep, '-', label ='closing price')
    ax1.axhline(closep[0], color='k', linewidth = 2)
    ax1.fill_between(date, closep, closep[0], where=(closep > closep[0]), facecolor='g', alpha=0.5)
    ax1.fill_between(date, closep, closep[0], where=(closep < closep[0]), facecolor ='r', alpha = 0.5)
    ax1.xaxis.label.set_color('c')
    ax1.yaxis.label.set_color('r')
    ax1.set_yticks([0,100,200,300,400,500,600,700,800,900,1000])

    for label in ax1.xaxis.get_ticklabels():
        label.set_rotation(45)
    ax1.grid(True, color= 'r', linestyle='-', linewidth=0.5)

    plt.subplots_adjust(left = 0.09, bottom =0.18, right= 0.94, top= 0.95, wspace=0.2, hspace=0)
    plt.title('stock')
    plt.xlabel('dates')
    plt.ylabel('price')
    plt.legend()
    plt.show()

我认为这是阻碍的地方

    canvas = FigureCanvasTkAgg(fig, master= root)  # A tk.DrawingArea.
    canvas.draw()
    canvas.get_tk_widget().pack(side=tk.TOP, fill=tk.BOTH, expand=1)

    toolbar = NavigationToolbar2Tk(canvas, root)
    toolbar.update()
    canvas.get_tk_widget().pack(side=tk.TOP, fill=tk.BOTH, expand=1)

graph_data('EBAY')
tk.mainloop()

再次感谢您;)

【问题讨论】:

  • 以什么方式失败?请充分说明您的问题。你得到一个错误吗?如果是这样,请提供完整的跟踪。看起来整个 graph_data() 代码都是多余的。你有没有尝试过先做一个非常简单的情节?

标签: python matplotlib tkinter


【解决方案1】:

从您提供的代码中很难完全理解问题所在。如果您可以更准确地了解错误/问题的性质或发布完整的代码,它可能会更容易提供帮助。

基本思想是当你嵌入到 tkinter 时,使用 matplotlib 方式(plt.show)显示图像是不够的,但你还需要创建一个画布元素并在其上绘制图像。所以我猜想graph_data(stock):方法的最后一部分应该修改,包括matplotlib中的方法draw_figure(代码here)例如:

def draw_figure(canvas, figure, loc=(0, 0)):
""" Draw a matplotlib figure onto a Tk canvas

loc: location of top-left corner of figure on canvas in pixels.
Inspired by matplotlib source: lib/matplotlib/backends/backend_tkagg.py
"""
  figure_canvas_agg = FigureCanvasAgg(figure)
  figure_canvas_agg.draw()
  figure_x, figure_y, figure_w, figure_h = figure.bbox.bounds
  figure_w, figure_h = int(figure_w), int(figure_h)
  photo = tk.PhotoImage(master=canvas, width=figure_w, height=figure_h)

  # Position: convert from top-left anchor to center anchor
  canvas.create_image(loc[0] + figure_w/2, loc[1] + figure_h/2, image=photo)

  # Unfortunately, there's no accessor for the pointer to the native renderer
  tkagg.blit(photo, figure_canvas_agg.get_renderer()._renderer, colormode=2)

  # Return a handle which contains a reference to the photo object
  # which must be kept live or else the picture disappears
  return photo

def graph_data(stock, canvas): 
  # do you really need stock parameter? it is not used
  fig = plt.figure()
  ax1 = plt.subplot2grid((1,1), (0,0))
  url_stock = 'https://pythonprogramming.net/yahoo_finance_replacement'
  source_code = urllib.request.urlopen(url_stock).read().decode()
  stock_data = []
  source_split = source_code.split('\n')

  for line in source_split[1:]:
    line_split = line.split(',')
    if len(line_split) == 7:
        if 'values' not in line and 'labels' not in line:
            stock_data.append(line)
  date, closep, highp, lowp, openp, adj_closep, volume = np.loadtxt(stock_data, delimiter =',', unpack= True, converters={0: bytespdate2num('%Y-%m-%d')})

  ax1.plot_date(date, closep, '-', label ='closing price')
  ax1.axhline(closep[0], color='k', linewidth = 2)
  ax1.fill_between(date, closep, closep[0], where=(closep > closep[0]), facecolor='g', alpha=0.5)
  ax1.fill_between(date, closep, closep[0], where=(closep < closep[0]), facecolor ='r', alpha = 0.5)
  ax1.xaxis.label.set_color('c')
  ax1.yaxis.label.set_color('r')
  ax1.set_yticks([0,100,200,300,400,500,600,700,800,900,1000])

  for label in ax1.xaxis.get_ticklabels():
    label.set_rotation(45)
  ax1.grid(True, color= 'r', linestyle='-', linewidth=0.5)

  plt.subplots_adjust(left = 0.09, bottom =0.18, right= 0.94, top= 0.95, wspace=0.2, hspace=0)
  plt.title('stock')
  plt.xlabel('dates')
  plt.ylabel('price')
  plt.legend()
  plt.show()

  fig_x, fig_y = 100, 100
  fig_photo = draw_figure(canvas, fig, loc=(fig_x, fig_y))
  fig_w, fig_h = fig_photo.width(), fig_photo.height()

所以它只是使用您创建的画布并在其上绘制您在 matplotlib 中绘制的图像。很难判断它是否会像这样工作,或者是否需要进行小编辑,因为我没有看到整个代码,但这应该会给你一个提示。

我可以向您指出完整的文档,其中提供了一个关于如何在 tkinter 中嵌入图像的简单示例, https://matplotlib.org/gallery/user_interfaces/embedding_in_tk_canvas_sgskip.html 你可以试试用这个作为测试

或者通过使用 PIL 库转换图像(这是我使用的解决方案)然后使用到 Tkinter (转换后更直接)https://solarianprogrammer.com/2018/04/20/python-opencv-show-image-tkinter-window/

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-05-03
    • 1970-01-01
    • 2013-09-14
    • 1970-01-01
    • 2014-10-06
    • 1970-01-01
    • 2019-04-08
    相关资源
    最近更新 更多