我的主python文件中有一个askopenfilename()
函数,当按下按钮时,该函数将从用户获取文件目录。我的主文件名为payroll.py
。
我还有另一个名为dataframes.py
的文件,该文件具有使用read_excel()
函数导入excel文件然后处理数据的功能。
此代码在payroll.py中:
import tkinter as tk
from tkinter import ttk
from tkinter import filedialog
import dataframes
class GUI(tk.Tk):
def __init__(self):
super().__init__()
self.title("SportClips Automation 0.0.1")
self.geometry('500x500')
self.resizable(width=False, height=False)
names = ['Instructions', 'Payroll']
self.nb = self.create_notebook(names)
self.menu = self.create_menus()
tab = self.nb.tabs['Instructions']
tk.Label(tab, text='-Select the "Payroll" tab to run Stylist
Compensation Worksheets').pack()
image = tk.PhotoImage(file="1.png")
tk.Label(tab, image=image).pack()
self.mainloop()
def create_notebook(self, names):
nb = MyNotebook(self, names)
nb.pack()
def add_label(parent, text, row, column):
label = ttk.Label(parent, text=text)
label.grid(row=row, column=column, sticky=tk.N, pady=10)
return label
def payroll():
nb.pr = dataframes.runpayroll(nb.name)
def getname():
nb.name = filedialog.askopenfilename(title="Select file",
filetypes=(("excel files",
"*.xls"), ("all files", "*.*")))
tab = nb.tabs['Payroll']
add_label(tab, 'Click this button to process payroll', 1, 8)
b1 = ttk.Button(tab, text="Run Payroll", command= payroll())
b1.grid(row=2, column=8)
b2 = ttk.Button(tab, text="Select SAR file", command=lambda:
getname())
b2.grid(row=3, column=8)
return nb
def create_menus(self):
menu = tk.Menu(self, tearoff=False)
self.config(menu=menu)
sub_menu = tk.Menu(menu, tearoff=False)
menu.add_cascade(label="File", menu=sub_menu)
sub_menu.add_separator()
sub_menu.add_command(label='Exit', command=self.destroy)
return menu
class MyNotebook(ttk.Notebook):
def __init__(self, master, names):
super().__init__(master, width=795, height=475)
# Create tabs & save them by name in a dictionary
self.tabs = {}
for name in names:
self.tabs[name] = tab = ttk.Frame(self)
self.add(tab, text=name)
GUI()
但是我猜这个错误:AttributeError: 'MyNotebook' object has no attribute 'name'
答案 0 :(得分:1)
如果您希望runpayroll
能够访问name
,则必须将其作为参数传递。
但是更大的问题是,您似乎并没有name
来通过它。
您在任何地方唯一调用name
的是该getname()
函数中的局部变量,该变量在该函数外部不可用。您所要做的只是return name
,但调用方对返回值不做任何事情,因为它只是Tkinter命令回调。
您需要考虑将这些内容存储在何处。通常的答案是创建一个类(或者是Notebook
的子类,或者是拥有Notebook
的“控制器”类),然后将它们存储为实例变量。作为次等选择,您有时可以将事物存储为全局(或非局部)变量。但是,无论您决定执行哪种操作,都必须有人将值分配给该实例或全局变量。然后,您可以将其传递给run_payroll
。
在这种情况下,您似乎已经有一个MyNotebook
类,并且正在创建该类的实例,所以也许这是存储内容的正确位置。
我们正在这样做,没有理由return
从某个函数中调用方将忽略结果的任何内容。而且,您不需要lambda: payroll()
;您可以只使用payroll
来达到相同的效果,但更易于理解(甚至更有效)。
所以:
def create_notebook(self, names):
nb = MyNotebook(self, names)
nb.pack()
# …
def payroll():
nb.pr = dataframes.runpayroll(nb.name)
def getname():
nb.name = filedialog.askopenfilename(title="Select file",
filetypes=(("excel
files", "*.xls"), ("all files", "*.*")))
# …
现在,只需更改runpayroll
即可使用该值:
def runpayroll(name):
df_sar = pd.read_excel(name,
sheet_name=0, header=None, skiprows=4)