我目前正在研究股票投資組合跟蹤器,我對變數從一幀傳遞到另一幀的方式感到非常困惑。到目前為止,我基本上有兩個框架,一個是樹視圖,第二個是 Userinputframe,一堆按鈕和條目小部件。
我的代碼應該使用這些條目小部件并將它們插入到我的樹視圖中。但是,現在它們進入了兩個不同的框架,我無法設法從 Userinputframe 中獲取()值以使用我的樹視圖,并且我收到錯誤訊息:'Frame' Object has no attribute 'Entry_ticker'。我在這里想念什么?
import tkinter
from tkinter import ttk
import datetime as dt
import yfinance as yf
import os
import csv
root_window = tkinter.Tk()
root_window.title('Python portfolio')
root_window.geometry('700x700')
# Frame functions
def call_first_frame():
second_frame.pack_forget()
first_frame.pack()
def call_second_frame():
first_frame.pack_forget()
second_frame.pack()
def call_third_frame():
second_frame.pack_forget()
def quit_program():
root_window.destroy()
# We create an csv flat file to store our values in
def create_database():
global header
header = ['Ticker', 'Volume', 'Purchased at', 'Current value']
with open('stocks.csv', 'w', encoding='UTF8', newline='') as f:
writer = csv.writer(f)
writer.writerow(header)
# we create a function to get the current share price of a ticker
def Shareprice(ticker):
ticker_yahoo = yf.Ticker(ticker)
data = ticker_yahoo.history()
return data.tail(1)['Close'].iloc[0]
# we use this to record a date of purchase
def stamp():
x = dt.datetime.now()
return x.strftime("%c")
# we fetch the price of the ticker entered
def CurrentPrice():
a=Shareprice(first_frame.Entry_ticker.get())
b=int(first_frame.Entry_volume.get())
return round(a*b,2)
# add an investment to the portfolio
def add_to_portfolio():
my_tree = ttk.Treeview(Treeviewframe, show='headings')
# Defining columns
my_tree['columns'] = ('Ticker', 'Volume', 'Purchased at', 'Current value')
# Column_formatting
my_tree.column('#0', anchor=tkinter.W, width=70, stretch=False)
my_tree.column('Ticker', anchor=tkinter.CENTER, width=50)
my_tree.column('Volume', anchor=tkinter.CENTER, width=50)
my_tree.column('Purchased at', anchor=tkinter.CENTER, width=175)
my_tree.column('Current value', anchor=tkinter.CENTER, width=150)
# Heading_formatting
my_tree.heading('#0', text='ID', anchor=tkinter.W)
my_tree.heading('Ticker', text='Ticker', anchor=tkinter.W)
my_tree.heading('Volume', text='Volume', anchor=tkinter.W)
my_tree.heading('Purchased at', text='Purchased at', anchor=tkinter.W)
my_tree.heading('Current value', text='Current value', anchor=tkinter.W)
global count
my_tree.insert(parent='', index='end', iid=count, text='',
values=(Userinputframe.Entry_ticker.get(), Userinputframe.Entry_volume.get(), stamp(), CurrentPrice()))
count = 1
# immediately after adding an investment in our treeview, we add our new investment to a our database
csvdata=[first_frame.Entry_ticker.get(), first_frame.Entry_volume.get(), stamp(), CurrentPrice()]
with open('stocks.csv', 'w', encoding='UTF8',newline='') as f:
writer = csv.writer(f)
writer.writerow(header)
with open('stocks.csv', 'a') as f:
writer = csv.writer(f)
writer.writerow(csvdata)
# We clear the entry widgets automatically when the button is pressed
first_frame.Entry_ticker.delete(0, tkinter.END)
first_frame.Entry_volume.delete(0, tkinter.END)
# remove one stock
def rmv_from_portfolio():
x = my_tree.selection()[0]
my_tree.delete(x)
# clear the portfolio (remove all stocks)
def rmv_all():
for record in my_tree.get_children():
my_tree.delete(record)
def start_tab_widgets():
# We initialize the Treeview to hold our portfolio
my_tree = ttk.Treeview(Treeviewframe, show='headings')
# Defining columns
my_tree['columns'] = ('Ticker', 'Volume', 'Purchased at', 'Current value')
# Column_formatting
my_tree.column('#0', anchor=tkinter.W, width=70, stretch=False)
my_tree.column('Ticker', anchor=tkinter.CENTER, width=50)
my_tree.column('Volume', anchor=tkinter.CENTER, width=50)
my_tree.column('Purchased at', anchor=tkinter.CENTER, width=175)
my_tree.column('Current value', anchor=tkinter.CENTER, width=150)
# Heading_formatting
my_tree.heading('#0', text='ID', anchor=tkinter.W)
my_tree.heading('Ticker', text='Ticker', anchor=tkinter.W)
my_tree.heading('Volume', text='Volume', anchor=tkinter.W)
my_tree.heading('Purchased at', text='Purchased at', anchor=tkinter.W)
my_tree.heading('Current value', text='Current value', anchor=tkinter.W)
# We find out if the user already has investments in his portfolio
path_name = 'stocks.csv'
if os.path.exists(path_name):
# then we read the data from the csv file, and make sure it appears in our treeview
old_data = []
else:
# then we create the database (CSV file)
create_database()
old_data = []
# We insert data in our portfolio
global count
count = 0
for record in old_data:
my_tree.insert(parent='', index='end', iid=count, text='', values=(record[0], record[1], record[2], record[3]))
count = 1
# widgets_user_input:Labels and entry
Lbl_ticker = tkinter.Label(Userinputframe, text='Ticker')
Lbl_ticker.grid(row=0, column=0, padx=10, pady=20, sticky='n')
Lbl_volume = tkinter.Label(Userinputframe, text='Volume')
Lbl_volume.grid(row=1, column=0, padx=10, pady=20, sticky='n')
Entry_ticker = tkinter.Entry(Userinputframe, text='Add ticker here...')
Entry_ticker.grid(row=0, column=1, pady=20, sticky='n', columnspan=2)
Entry_volume = tkinter.Entry(Userinputframe, text='Add nb of shares here...')
Entry_volume.grid(row=1, column=1, pady=20, sticky='n', columnspan=2)
# Buttons to add and remove records
Btn_add_record = tkinter.Button(Userinputframe, text='Add to portfolio', command=add_to_portfolio)
Btn_add_record.grid(row=2, column=1, pady=20, sticky='ns')
Btn_rmv_record = tkinter.Button(Userinputframe, text='Remove one selected stock', command=rmv_from_portfolio)
Btn_rmv_record.grid(row=3,column=1, pady=20, sticky='n')
Btn_rmv_all = tkinter.Button(Userinputframe, text='Clear my portfolio', command=rmv_all)
Btn_rmv_all.grid(row=4, column=1, pady=20, sticky='n')
# we pack our Tree view onto our frame
my_tree.pack(in_=Treeviewframe, pady=20, padx=0, fill='y')
# we place those two frames one after the other
Treeviewframe.pack(in_=first_frame, pady=20)
Treeviewframe['borderwidth'] = 0
Userinputframe.pack(in_=first_frame, pady=20)
Userinputframe['borderwidth'] = 0
# Buttons to leave the program
# We declare our frames
first_frame = tkinter.ttk.Frame(root_window)
first_frame.pack()
# we define two sub-frames to work into
Treeviewframe = tkinter.ttk.Frame(first_frame)
Userinputframe = tkinter.ttk.Frame(first_frame)
second_frame = tkinter.Frame(root_window)
second_frame.pack()
third_frame = tkinter.Frame(root_window)
third_frame.pack()
# We hide all frames in reverse order, but leave the first frame visible
start_tab_widgets()
'''
portfolio_widgets()
reco_widgets()
'''
# Hide all frames in reverse order, but we leave the first frame visible
third_frame.pack_forget()
second_frame.pack_forget()
# we add this program to the main loop
root_window.mainloop()
uj5u.com熱心網友回復:
查看代碼,錯誤:Frame' Object has no attribute 'Entry_ticker'是預期的。
Entry_ticker是一個區域變數,而不是Userinputframe.
這里有幾個選項:
選項 1:將您的條目定義為全域變數
entry_ticker = None
....
...
...
def start_tab_widgets():
...
...
global entry_ticker
entry_ticker = tkinter.Entry(Userinputframe, text='Add ticker here...')
entry_ticker.grid(row=0, column=1, pady=20, sticky='n', columnspan=2)
def add_to_portfolio():
...
...
#access entry_ticker
global entry_ticker
value = entry_ticker.get()
選項 2:為您的框架創建一個新類并定義一個類級別變數
class UserInputFrame:
def __init__(self, parent):
self.frame = tkinter.ttk.Frame(parent)
self.entry_ticker = tkinter.Entry(self.frame, text='Add ticker here...')
self.entry_ticker.grid(row=0, column=1, pady=20, sticky='n', columnspan=2)
def start_tab_widgets():
....
....
....
# Create class instance
user_input_frame = UserInputFrame(root_window)
# Access the entry_ticker value
user_input_frame.entry_ticker.get()
選項 3:使用 tkinter.StringVar()
現在,訪問該值的最合適的選項是<type>Var()在您的情況下使用 tkinter可以使用 StringVar()。因此,當您創建條目時
# create the stringvar
entry_ticker_var = tkinter.StringVar()
# Use the var while createing entry (textvariable=entry_ticker_var)
entry_ticker = tkinter.Entry(self.frame, text='Add ticker here...', textvariable=entry_ticker_var)
....
....
現在,在使用它時只需呼叫entry_ticker.get()或者如果您想更新條目中的文本,您可以entry_ticker.set("New Value")
您還可以將跟蹤事件系結到此變數entry_ticker.trace_add('write', on_change)。on_change每當您的該變數的值發生更改時(即每當用戶將輸入寫入文本框時),都會呼叫此處的函式
選項 4:選項 2 和 3 一起(推薦)
類用戶輸入幀:
def __init__(self, parent):
# create the variable
self.entry_ticker_var = tkinter.StringVar()
# create frame
frame = tkinter.ttk.Frame(parent)
# create text box
entry_ticker = tkinter.Entry(self.frame, text='Add ticker here...', textvariable=self.entry_ticker_var)
entry_ticker.grid(row=0, column=1, pady=20, sticky='n', columnspan=2)
def start_tab_widgets():
....
....
....
# Create class instance
user_input_frame = UserInputFrame(root_window)
# Access the entry_ticker value
user_input_frame.entry_ticker_var.get()
參考:
Python Tkinter
python Tkinter 模塊
在旁注中,如果您想訪問框架的子小部件,您可能需要使用 winfo_children()
for child in Userinputframe.winfo_children():
widget_type = child.winfo_class()
if widget_type == 'Entry':
# do stuff
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/409461.html
標籤:
下一篇:我正在ExpandebleTableview創建一個演示,擴展作業正常...但是在點擊didselect行時遇到問題
