0

When I put graphs on my tkinter window, it shows all of the graphs, not just one. The way I want it is you press a button, and the corresponding graph will show up (along with some other data). I believe its an issue with my buttons, as its trying to call the function for all of the stocks at once, rather than just one at a time based on what button you press.

import numpy as np
import datetime as dt
import yahoo_finance as yf
import matplotlib.pyplot as plt
from Tkinter import *
import quandl

from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg


root=Tk()
root.geometry('800x800')
root.title("Stock Information")

f1=Frame(root, width=100, height=100)

f1.pack()


today=dt.date.today()
thirty_days=dt.timedelta(days=43)   

thirty_days_ago=today-thirty_days



def stock_info(stock_name):


    stock=yf.Share(stock_name)
    stock_price=stock.get_price()

    name_price_label=Label(f1, text=(stock_name,':', stock_price),font=("Times New Roman",23))
    name_price_label.grid(row=1, column=3)





    data = quandl.get("WIKI/"+str(stock_name), start_date=str(thirty_days_ago), end_date=str(today),column_index=4)

    fig = plt.figure(1)
    t = np.arange(0.0,3.0,0.01)
    s = np.sin(np.pi*t)
    plt.plot(data)

    canvas = FigureCanvasTkAgg(fig, master=f1)
    plot_widget = canvas.get_tk_widget()
    plot_widget.grid()


apple_button=Button(root,text='AAPL', command=stock_info('AAPL'))

tesla_button=Button(root,text='TSLA', command=stock_info('TSLA'))

google_button=Button(root,text='GOOG', command=stock_info('GOOG'))


apple_button.pack(anchor='w')
tesla_button.pack(anchor='w')
google_button.pack(anchor='w')




root.mainloop()
Addison
  • 403
  • 8
  • 24

1 Answers1

0

Replace your button creations with;

apple_button=Button(root,text='AAPL', command=lambda:stock_info('AAPL'))

tesla_button=Button(root,text='TSLA', command=lambda:stock_info('TSLA'))

google_button=Button(root,text='GOOG', command=lambda:stock_info('GOOG'))

This ensures the function is called when the button is clicked rather than when it is created.

This however keeps adding new plots anytime a button is clicked without replacing the old plot. You need to rewrite the code to delete the old plot before adding the new one. I exceeded my daily Quandl calls limit as an anonymous user so I couldn't complete this part.

UPDATE

Try this:

import numpy as np
import datetime as dt
import yahoo_finance as yf
import matplotlib.pyplot as plt
from Tkinter import *
import quandl

from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg


root=Tk()
root.geometry('800x800')
root.title("Stock Information")

## Create a main frame
fmain=Frame(root, width=100, height=100)
fmain.pack()

#*** Option 2 ***#
# Not needed if you use Original Option in stock_info function
## Create a secondary frame that will be destroy when the next button is clicked
f1=Frame(fmain, width=100, height=100)
f1.pack()

today=dt.date.today()
thirty_days=dt.timedelta(days=43)   

thirty_days_ago=today-thirty_days



def stock_info(stock_name):
    global f1

    #*** Original Option ***#
    ## Destroy the secondary frame if it exists
    # try: 
    #     f1.destroy()
    # except:
    #     pass

    #*** Option 2 ***#
    ## Destroy the secondary frame
    f1.destroy()

    ## Create a secondary frame that will be destroy when the next button is clicked
    f1=Frame(fmain, width=100, height=100)
    f1.pack()

    stock=yf.Share(stock_name)
    stock_price=stock.get_price()

    name_price_label=Label(f1, text=(stock_name,':', stock_price),font=("Times New Roman",23))
    name_price_label.grid(row=0, column=2)


    data = quandl.get("WIKI/"+str(stock_name), start_date=str(thirty_days_ago), end_date=str(today),column_index=4)

    fig = plt.figure(figsize=(10,5)) #Change graph size here
    t = np.arange(0.0,3.0,0.01)
    s = np.sin(np.pi*t)
    plt.plot(data)


    canvas = FigureCanvasTkAgg(fig, master=f1)
    plot_widget = canvas.get_tk_widget()

    #Change graph placement here
    #Any widget you grid in row less than 5 will be above this plot
    #Any widget you grid in column less than 2 (0 or 1) will to the left
    #You can chage this row and column number to whatever is appropriate
    plot_widget.grid(row=5, column=2) 


apple_button=Button(root,text='AAPL', command=lambda:stock_info('AAPL'))
tesla_button=Button(root,text='TSLA', command=lambda:stock_info('TSLA'))
google_button=Button(root,text='GOOG', command=lambda:stock_info('GOOG'))


apple_button.pack(anchor='w')
tesla_button.pack(anchor='w')
google_button.pack(anchor='w')

root.mainloop()
Khristos
  • 973
  • 2
  • 11
  • 22
  • Oh ok, the help is much appreciated! As for updating the graph info and stock info, how would I do that without having to close and reopen the tkinter window? – Addison May 21 '17 at 18:59
  • I updated the answer, try it and let me know if it works. – Khristos May 21 '17 at 22:21
  • Thank you that works very well! Could you explain how the global and try part work? I don't understand how that part works. Also is there a way to adjust size and placement of the graphs? I would love for them to be over on the right/bottom so I can display more info towards the top. Thanks again!! – Addison May 22 '17 at 13:12
  • Updated answer to include graph size, placement of name and price label, and some comments. – Khristos May 22 '17 at 14:34
  • The `global` keyword creates a variable in the global namespace (makes the variable available to other functions/methods outside the current function). In this case, it makes the same f1 available to multiple calls of the function, rather than each function call creating a local f1. This makes it possible for f1 to be modified/deleted by any of the function calls. You can read more about it in [this link](http://www.python-course.eu/global_vs_local_variables.php) [or this one](https://stackoverflow.com/questions/423379/using-global-variables-in-a-function-other-than-the-one-that-created-them) – Khristos May 22 '17 at 14:40
  • The `try` and `except` block is as the name suggests, it tries to delete f1 and if not possible, it just ignores the error and continue with the rest of the code. This is needed because the first time you call the function, there is no graph and there is no f1, this takes care of the error. I'm actually going to update the answer to avoid using the `try` and `except` block. You can then use the new answer if that makes more sense. – Khristos May 22 '17 at 14:47