简体   繁体   中英

Why is my treeview messing up my columns in tkinter?

enter image description here

Hi there, Im doing a tkinter project and I'm trying to show some of my data to the user. For some reason, my view is messing up my formatting ie i have a column that shows up for no reason and the how many shares do you want column is off. How can I solve this? this project uses tkinter and I'm almost there except i really can't find a way to solve this display issue. Any other comments on how to make my code nicer is appreciated, this is my first python project.

import tkinter
import tkinter.ttk
import datetime
import yfinance as yf
import main_backend as mb
import pandas as pd
import numpy as np
import csv as csv


# create classes
class Investment(object):
    def __init__(self,ticker,volume,Date_of_purchase,avg_price):
        self.ticker = ticker
        self.volume = volume
        self.Date_of_purchase = Date_of_purchase
        self.avg_price = avg_price

def GetCurrentValue(ticker):
    ticker_yahoo = yf.Ticker(ticker)
    data = ticker_yahoo.history()
    return(data.tail(1)['Close'].iloc[0])

'''
def file_open():
    try:
        df = pd.read_excel(stocks.csv)
    except FileNotFoundError:
        my_label.config(text="error, we couldn't find the file!")

    #this clears out past data
    clear_tree()

    #show new tree view
    my_tree['column']=list(df.columns)
    my_tree['show']='headings'

    #loop
    for column in my_tree['column']:
        my_tree.heading(column,text=column)

    #display data
    df_rows = df.to_numpy().tolist()
    for row in df_rows:
        my_tree.insert('','end',values=row)

    my_tree.grid(row=25,column=0)


def clear_tree():
    my_tree.delete(*my_tree.get_childen())
'''
def initialize_db():
    mb.create_database()

# we populate the start tab
def start_tab_widgets():
    # Create the label for the frame
    first_window_label = tkinter.ttk.Label(first_frame, text='Welcome to your stock portfolio!')
    first_window_label.grid(column=0, row=0, pady=10, padx=10, sticky=(tkinter.W))

    # start_tab functionalities
    lbl_lucky = tkinter.ttk.Label(first_frame,
                                  text='Place your orders below, your portfolio will be generated after you fill in your orders, and click Generate my portfolio')
    lbl_lucky.grid(column=0, row=1, padx=10, sticky=(tkinter.W))
    lbl_insert_stickers = tkinter.ttk.Label(first_frame,text='Insert tickers in this column')
    lbl_insert_stickers.grid(column=0,row=2,pady=10, padx=10, sticky=(tkinter.W))
    lbl_how_many_shares = tkinter.ttk.Label(first_frame,text='How many shares do you want?')
    lbl_how_many_shares.grid(column=1,row=2,pady=10, padx=10, sticky=(tkinter.W))


    E1_tickers = tkinter.ttk.Entry(first_frame)
    E1_tickers.grid(column=0,row=10,pady=10, padx=10, sticky=(tkinter.W))
    E2_tickers = tkinter.ttk.Entry(first_frame)
    E2_tickers.grid(column=0, row=11, pady=10, padx=10, sticky=(tkinter.W))
    E3_tickers = tkinter.ttk.Entry(first_frame)
    E3_tickers.grid(column=0, row=12, pady=10, padx=10, sticky=(tkinter.W))
    E4_tickers = tkinter.ttk.Entry(first_frame)
    E4_tickers.grid(column=0, row=13, pady=10, padx=10, sticky=(tkinter.W))
    E5_tickers = tkinter.ttk.Entry(first_frame)
    E5_tickers.grid(column=0, row=14, pady=10, padx=10, sticky=(tkinter.W))

    E1_nb_of_shares = tkinter.ttk.Entry(first_frame)
    E1_nb_of_shares.grid(column=1,row=10,pady=10, padx=10, sticky=(tkinter.W))
    E2_nb_of_shares = tkinter.ttk.Entry(first_frame)
    E2_nb_of_shares.grid(column=1, row=11, pady=10, padx=10, sticky=(tkinter.W))
    E3_nb_of_shares = tkinter.ttk.Entry(first_frame)
    E3_nb_of_shares.grid(column=1, row=12, pady=10, padx=10, sticky=(tkinter.W))
    E4_nb_of_shares = tkinter.ttk.Entry(first_frame)
    E4_nb_of_shares.grid(column=1, row=13, pady=10, padx=10, sticky=(tkinter.W))
    E5_nb_of_shares = tkinter.ttk.Entry(first_frame)
    E5_nb_of_shares.grid(column=1, row=14, pady=10, padx=10, sticky=(tkinter.W))

    #this records a time stamp when we print the user output
    x = datetime.datetime.now()
    stamp = x.strftime("%c")

    def get_current_price(symbol):
        ticker = yf.Ticker(symbol)
        todays_data = ticker.history(period='1d')
        return todays_data['Close'][0]

    def generate_porfolio():
        #this function aggregates both the ticker and the number of shares, as of now it's printed, but wont be in the final result
        investment1=list(E1_tickers.get()+','+E1_nb_of_shares.get()+','+stamp+str(GetCurrentValue(ticker=E1_tickers.get())))
        investment2=list(E2_tickers.get()+','+E2_nb_of_shares.get()+','+stamp+str(GetCurrentValue(ticker=E2_tickers.get())))
        investment3=list(E3_tickers.get()+','+E3_nb_of_shares.get()+','+stamp+str(GetCurrentValue(ticker=E3_tickers.get())))
        investment4=list(E4_tickers.get()+','+E4_nb_of_shares.get()+','+stamp+str(GetCurrentValue(ticker=E4_tickers.get())))
        investment5=list(E5_tickers.get()+','+E5_nb_of_shares.get()+','+stamp+str(GetCurrentValue(ticker=E5_tickers.get())))
        #return(str(investment1+investment2+investment3+investment4+investment5))' leave it here for now
        initialize_db()
        mb.update_data(E1_tickers.get(),E1_nb_of_shares.get(),stamp,GetCurrentValue(ticker=E1_tickers.get()))
        mb.update_data(E2_tickers.get(),E2_nb_of_shares.get(),stamp,GetCurrentValue(ticker=E2_tickers.get()))
        mb.update_data(E3_tickers.get(),E3_nb_of_shares.get(),stamp,GetCurrentValue(ticker=E3_tickers.get()))
        mb.update_data(E4_tickers.get(),E4_nb_of_shares.get(),stamp,GetCurrentValue(ticker=E4_tickers.get()))
        mb.update_data(E5_tickers.get(),E5_nb_of_shares.get(),stamp,GetCurrentValue(ticker=E5_tickers.get()))

        #Now that the data is in excel, we load it into the front page
        tv_data = tkinter.ttk.Treeview(first_frame,columns=('ticker', 'volume','Date of Purchase', 'Average price'))

        tv_data.heading('ticker',text='ticker')
        tv_data.heading('volume', text='volume')
        tv_data.heading('Date of Purchase', text='Date of Purchase')
        tv_data.heading('Average price', text='Average price')
        tv_data.grid(row=20,column=0,pady=10, padx=10, sticky=(tkinter.W))

        with open('stocks.csv') as f:
                reader = csv.DictReader(f,delimiter=',')
                for row in reader:
                    ticker=row['ticker']
                    volume=row['volume']
                    Date=row['Date of Purchase']
                    price=row['Average price']
                    tv_data.insert("",1,values=(ticker,volume,Date,price))










        #lbl_userinput = tkinter.ttk.Label(first_frame,text=userinput) #dont forget to delete this
        #lbl_userinput.grid(column=1,row=98,pady=10, padx=10, sticky=(tkinter.W)) #dont forget to delete this


    #we create a button to output user input
    Btn_ticker_value=tkinter.ttk.Button(first_frame,text='Generate my portfolio',command=generate_porfolio)
    Btn_ticker_value.grid(column=0,row=90,pady=10, padx=10, sticky=(tkinter.W))

    # Create the buttons to move frames and exit
    first_window_quit_button = tkinter.Button(first_frame, text = "Quit", command = quit_program)
    first_window_quit_button.grid(column=0, row=100, padx=10,pady=10, sticky=(tkinter.W))
    first_window_next_button = tkinter.Button(first_frame, text = "Next", command = call_second_frame_on_top)
    first_window_next_button.grid(column=1, row=100, padx=10,pady=10, sticky=(tkinter.W))

'''
    #we initiate the five investments
    Investment1=Investment(E1_tickers.get(),E1_nb_of_shares.get(),stamp,get_current_price(E1_tickers))
    Investment2=Investment(E2_tickers.get(),E2_nb_of_shares.get(),stamp,get_current_price(E2_tickers))
    Investment3=Investment(E3_tickers.get(),E3_nb_of_shares.get(),stamp,get_current_price(E3_tickers))
    Investment4=Investment(E4_tickers.get(),E4_nb_of_shares.get(),stamp,get_current_price(E4_tickers))
    Investment5=Investment(E5_tickers.get(),E5_nb_of_shares.get(),stamp,get_current_price(E5_tickers))
'''


def portfolio_widgets():
    # Create the label for the frame
    second_window_label = tkinter.ttk.Label(second_frame, text='Portfolio')
    second_window_label.grid(column=0, row=0, pady=10, padx=10, sticky=(tkinter.W))

    # Create the button for the frame
    second_window_back_button = tkinter.Button(second_frame, text = "Back", command = call_first_frame_on_top)
    second_window_back_button.grid(column=0, row=10, pady=10, sticky=(tkinter.W))
    second_window_next_button = tkinter.Button(second_frame, text = "Next", command = call_third_frame_on_top)
    second_window_next_button.grid(column=1, row=10, pady=10, sticky=(tkinter.W))

    #insert porfolio functionalities here
    #first we populate with the portfolio
    lbl_Portfolios_title = tkinter.Label(second_frame, text="Portfolios", bg='orange')
    lbl_Portfolios_title.grid(row=4, column=0, sticky='w', pady=2)
    lbl_Portfolio = tkinter.Label(second_frame, text="Portfolio", bg='orange')
    lbl_Portfolio.grid(row=5, column=0, sticky='w', pady=2)
    lbl_Last = tkinter.Label(second_frame, text="Last", bg='orange')
    lbl_Last.grid(row=5, column=1, sticky='w', pady=2)
    lbl_Change = tkinter.Label(second_frame, text="Change", bg='orange')
    lbl_Change.grid(row=5, column=2, sticky='w', pady=2)
    lbl_Unrealised = tkinter.Label(second_frame, text="Unrealised Gain/Loss", bg='orange')
    lbl_Unrealised.grid(row=5, column=3, sticky='w', pady=2)
    lbl_Total_Return = tkinter.Label(second_frame, text="Total Return", bg='orange')
    lbl_Total_Return.grid(row=5, column=4, sticky='w', pady=2)
    lbl_name_portfolio = tkinter.Label(second_frame, text="Needs work", bg='orange')
    lbl_name_portfolio.grid(row=6, column=0, sticky='w', pady=2)
    lbl_Last_inEUR = tkinter.Label(second_frame, text="Needs work", bg='orange')
    lbl_Last_inEUR.grid(row=6, column=1, sticky='w', pady=2)
    lbl_Change_inper = tkinter.Label(second_frame, text="Needs work", bg='orange')
    lbl_Change_inper.grid(row=6, column=2, sticky='w', pady=2)
    lbl_Unrealized_inEUR = tkinter.Label(second_frame, text="Needs work", bg='orange')
    lbl_Unrealized_inEUR.grid(row=6, column=3, sticky='w', pady=2)
    lbl_Total_ReturninEUR = tkinter.Label(second_frame, text="Needs work", bg='orange')
    lbl_Total_ReturninEUR.grid(row=6, column=4, sticky='w', pady=2)

    # we populate the Portfolio movers section of the second frame
    lbl_Port_movers_title = tkinter.Label(second_frame, text="Portfolio Movers", bg='green')
    btn1 = tkinter.Button(second_frame, text='I want to see my gainers', bd='5', command=())
    btn2 = tkinter.Button(second_frame, text='I want to see my losers', bd='5', command=())

    # We grid the Portfolio movers part
    lbl_Port_movers_title.grid(row=7, column=0, sticky='w', pady=2)
    btn1.grid(row=8, column=0)
    btn2.grid(row=8, column=1)

def reco_widgets():
    # Create the label for the frame
    third_window_label = tkinter.ttk.Label(third_frame, text='Recommendation tab')
    third_window_label.grid(column=0, row=0, pady=10, padx=10, sticky=(tkinter.N))

    # Create the button for the frame
    third_window_back_button = tkinter.Button(third_frame, text = "Back", command = call_second_frame_on_top)
    third_window_back_button.grid(column=0, row=1, pady=10, sticky=(tkinter.N))
    third_window_quit_button = tkinter.Button(third_frame, text = "Quit", command = quit_program)
    third_window_quit_button.grid(column=1, row=1, pady=10, sticky=(tkinter.N))

def call_first_frame_on_top():
    # This function can be called only from the second window.
    # Hide the second window and show the first window.
    second_frame.grid_forget()
    first_frame.grid(column=0, row=0, padx=20, pady=5, sticky=(tkinter.W, tkinter.N, tkinter.E))

def call_second_frame_on_top():
    # This function can be called from the first and third windows.
    # Hide the first and third windows and show the second window.
    first_frame.grid_forget()
    third_frame.grid_forget()
    second_frame.grid(column=0, row=0, padx=20, pady=5, sticky=(tkinter.W, tkinter.N, tkinter.E))

def call_third_frame_on_top():
    # This function can only be called from the second window.
    # Hide the second window and show the third window.#
    second_frame.grid_forget()
    third_frame.grid(column=0, row=0, padx=20, pady=5, sticky=(tkinter.W, tkinter.N, tkinter.E))

def quit_program():
    root_window.destroy()

# we run the main program now

# Create the root GUI window.
root_window = tkinter.Tk()
root_window.title('Stock portfolio')
root_window.geometry('1000x800')

# Define window size
window_width = 1000
window_heigth = 1000

# Create frames inside the root window to hold other GUI elements. All frames must be created in the main program, otherwise they are not accessible in functions.
first_frame=tkinter.ttk.Frame(root_window, width=window_width, height=window_heigth)
first_frame['borderwidth'] = 2
first_frame.grid(column=0, row=0, padx=20, pady=5, sticky=(tkinter.W, tkinter.W, tkinter.E))

second_frame=tkinter.ttk.Frame(root_window, width=window_width, height=window_heigth)
second_frame['borderwidth'] = 2
second_frame.grid(column=0, row=0, padx=20, pady=5, sticky=(tkinter.W, tkinter.W, tkinter.E))

third_frame=tkinter.ttk.Frame(root_window, width=window_width, height=window_heigth)
third_frame['borderwidth'] = 2
third_frame.grid(column=0, row=0, padx=20, pady=5, sticky=(tkinter.W, tkinter.W, tkinter.E))

# Create all widgets to all frames
reco_widgets()
portfolio_widgets()
start_tab_widgets()

# Hide all frames in reverse order, but leave first frame visible (unhidden).
third_frame.grid_forget()
second_frame.grid_forget()

# Start tkinter event - loop
root_window.mainloop()

The extra column in the treeview is the tree column which can be disabled by setting show='headings' when creating the treeview:

tv_data = tkinter.ttk.Treeview(first_frame, columns=('ticker', 'volume','Date of Purchase', 'Average price'), show='headings')

The display issue on the "How many shares do you want?" column is because the width of the first column are long due to the label lbl_lucky . It can be fixed by setting columnspan=2 (you can try any value > 1 to suit your case) in lbl_lucky.grid(...) and tv_data.grid(...) :

lbl_lucky.grid(column=0, row=1, padx=10, sticky=(tkinter.W), columnspan=2)
tv_data.grid(row=20, column=0, pady=10, padx=10, sticky=(tkinter.W), columnspan=2)

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM