我正在使用带有OOP概念的Python Tkinter制作一个计算器项目,但我无法找出函数类的问题。函数类负责除法、乘法等。窗口类是画布,我还制作了另外两个类,用于按钮和显示。函数类比较乱。
我认为,这是代码中的概念问题,但我真的无法弄清楚。
import tkinter as tk
from tkinter import ttk
from tkinter import *
class Window(tk.Tk):
def __init__(self,size,title):
super().__init__()
self.geometry(f"{size[0]}x{size[1]}")
self.minsize(size[0],size[1])
self.title(title)
# self.attributes('-alpha',0.85)
#placing button frame
self.button_frame = Button_frame(self)
self.display_frame = Display_frame(self)
#crating frame for the widgets
#animated slidebar
class Window_Frame(ttk.Frame):
def __init__(self,parent,start_pos,end_pos):
super().__init__(master= parent)
#general attributes
self.start_pos= start_pos
self.end_pos = end_pos
self.width = abs(start_pos - end_pos)
self.place(relx=self.start_pos,rely=0, relheight=1,relwidth=self.width)
#frame for the display
class Display_frame(ttk.Frame):
def __init__(self,parent):
super().__init__(master= parent)
self.pack(expand = True, fill = 'both',side = 'top')
self.text_input = StringVar()
self.entry_fild = ttk.Entry(self, textvariable=self.text_input)
self.entry_fild.pack(expand=True, fill='both')
#frame for the button widget
class Button_frame(ttk.Frame):
def __init__(self,parent):
super().__init__(master= parent)
self.pack(side='bottom',expand = True, fill = 'both')
Frame_Buttons(self)
class Frame_Buttons(ttk.Button):
def __init__(self,parent):
super().__init__(master=parent)
self.pack(side='bottom',expand = True,fill = 'both',pady=5,padx = 5)
self.buttons()
self.funct = Function()
self.delete = self.funct.delete
self.clear = self.funct.clear
self.eval = self.funct.eval
def buttons(self):
button1 = ttk.Button(self, text="1",command=lambda: self.funct.numb_press('1'))
button2 = ttk.Button(self, text="2", command=lambda: self.funct.numb_press('2'))
button3 = ttk.Button(self, text="3", command=lambda: self.funct.numb_press('3'))
button4 = ttk.Button(self, text="4", command=lambda: self.funct.numb_press('4'))
button5 = ttk.Button(self, text="5", command=lambda: self.funct.numb_press('5'))
button6 = ttk.Button(self, text="6", command=lambda: self.funct.numb_press('6'))
button7 = ttk.Button(self, text="7", command=lambda: self.funct.numb_press('7'))
button8 = ttk.Button(self, text="8", command=lambda: self.funct.numb_press('8'))
button9 = ttk.Button(self, text="9", command=lambda: self.funct.numb_press('9'))
button0 = ttk.Button(self, text="0", command=lambda: self.funct.numb_press('0'))
# opoaration button
but_add = ttk.Button(self, text="+",command=lambda: self.funct.numb_press('+'))
but_sub = ttk.Button(self, text="-",command=lambda: self.funct.numb_press('-'))
but_mul = ttk.Button(self, text="*",command=lambda: self.funct.numb_press('*'))
but_div = ttk.Button(self, text="/",command=lambda: self.funct.numb_press('/'))
but_per = ttk.Button(self, text="%",command=lambda: self.funct.numb_press('%'))
but_bra = ttk.Button(self, text='(',command=lambda: self.funct.numb_press('('))
but_bra2 = ttk.Button(self, text=')',command=lambda:self.funct.numb_press(')'))
but_eql = ttk.Button(self, text="=", command=self.eval)
but_del = ttk.Button(self, text="DEL", command=self.delete)
but_clr = ttk.Button(self, text="CLR", command=self.clear)
button1.grid(row=0, column=0)
button2.grid(row=0, column=1)
button3.grid(row=0, column=2)
button4.grid(row=1, column=0)
button5.grid(row=1, column=1)
button6.grid(row=1, column=2)
button7.grid(row=2, column=0)
button8.grid(row=2, column=1)
button9.grid(row=2, column=2)
button0.grid(row=3, column=1)
but_add.grid(column=3, row=0)
but_sub.grid(column=3, row=1)
but_mul.grid(column=3, row=2)
but_div.grid(column=4, row=0)
but_del.grid(column=4, row=1)
but_clr.grid(column=4, row=2)
but_per.grid(column=3, row=3)
but_eql.grid(column=4, row=3)
but_bra.grid(column=0, row=3)
but_bra2.grid(column=2, row=3)
class Function():
def __init__(self):
# definingg variables for oparation functions
self.Expression = ""
# defining the functions
def numb_press(self, numb):
self.expression = numb
self.display_frame
def clear(self):
self.expression = ""
self.text_variable.set(self.expression)
def delete(self):
temp = self.text_variable.get()
self.text_variable.set(str(temp[:-1]))
def eval (self):
temp = self.text_variable.get()
self.text_variable.input(str(eval(temp)))
if __name__ == '__main__':
app =Window((500,450),'app')
app.mainloop()
这里有几个错误。
buttons
的 delete
、clear
和 eval
属性之前调用 Frame_Buttons
。因此,当实例化
but_eql
时,它会失败,因为还没有
self.eval
。如果您将该调用移到最后,您就可以让它运行。
import tkinter as tk
from tkinter import ttk
from tkinter import *
class Window(tk.Tk):
def __init__(self,size,title):
super().__init__()
self.geometry(f"{size[0]}x{size[1]}")
self.minsize(size[0],size[1])
self.title(title)
# self.attributes('-alpha',0.85)
#placing button frame
self.display_frame = Display_frame(self)
self.button_frame = Button_frame(self)
#creating frame for the widgets
#animated slidebar
class Window_Frame(ttk.Frame):
def __init__(self,parent,start_pos,end_pos):
super().__init__(master= parent)
#general attributes
self.start_pos= start_pos
self.end_pos = end_pos
self.width = abs(start_pos - end_pos)
self.place(relx=self.start_pos,rely=0, relheight=1,relwidth=self.width)
#frame for the display
class Display_frame(ttk.Frame):
def __init__(self,parent):
super().__init__(master= parent)
self.pack(expand = True, fill = 'both',side = 'top')
self.text_input = StringVar()
self.entry_fild = ttk.Entry(self, textvariable=self.text_input)
self.entry_fild.pack(expand=True, fill='both')
#frame for the button widget
class Button_frame(ttk.Frame):
def __init__(self,parent):
super().__init__(master=parent)
self.parent = parent
self.pack(side='bottom',expand = True, fill = 'both')
Frame_Buttons(self)
class Frame_Buttons(ttk.Button):
def __init__(self,parent):
super().__init__(master=parent)
self.pack(side='bottom',expand = True,fill = 'both',pady=5,padx = 5)
self.funct = Function(parent.parent.display_frame.text_input)
self.delete = self.funct.delete
self.clear = self.funct.clear
self.eval = self.funct.eval
self.buttons()
def buttons(self):
button1 = ttk.Button(self, text="1",command=lambda: self.funct.numb_press('1'))
button2 = ttk.Button(self, text="2", command=lambda: self.funct.numb_press('2'))
button3 = ttk.Button(self, text="3", command=lambda: self.funct.numb_press('3'))
button4 = ttk.Button(self, text="4", command=lambda: self.funct.numb_press('4'))
button5 = ttk.Button(self, text="5", command=lambda: self.funct.numb_press('5'))
button6 = ttk.Button(self, text="6", command=lambda: self.funct.numb_press('6'))
button7 = ttk.Button(self, text="7", command=lambda: self.funct.numb_press('7'))
button8 = ttk.Button(self, text="8", command=lambda: self.funct.numb_press('8'))
button9 = ttk.Button(self, text="9", command=lambda: self.funct.numb_press('9'))
button0 = ttk.Button(self, text="0", command=lambda: self.funct.numb_press('0'))
# opoaration button
but_add = ttk.Button(self, text="+",command=lambda: self.funct.numb_press('+'))
but_sub = ttk.Button(self, text="-",command=lambda: self.funct.numb_press('-'))
but_mul = ttk.Button(self, text="*",command=lambda: self.funct.numb_press('*'))
but_div = ttk.Button(self, text="/",command=lambda: self.funct.numb_press('/'))
but_per = ttk.Button(self, text="%",command=lambda: self.funct.numb_press('%'))
but_bra = ttk.Button(self, text='(',command=lambda: self.funct.numb_press('('))
but_bra2 = ttk.Button(self, text=')',command=lambda:self.funct.numb_press(')'))
but_eql = ttk.Button(self, text="=", command=self.eval)
but_del = ttk.Button(self, text="DEL", command=self.delete)
but_clr = ttk.Button(self, text="CLR", command=self.clear)
button1.grid(row=0, column=0)
button2.grid(row=0, column=1)
button3.grid(row=0, column=2)
button4.grid(row=1, column=0)
button5.grid(row=1, column=1)
button6.grid(row=1, column=2)
button7.grid(row=2, column=0)
button8.grid(row=2, column=1)
button9.grid(row=2, column=2)
button0.grid(row=3, column=1)
but_add.grid(column=3, row=0)
but_sub.grid(column=3, row=1)
but_mul.grid(column=3, row=2)
but_div.grid(column=4, row=0)
but_del.grid(column=4, row=1)
but_clr.grid(column=4, row=2)
but_per.grid(column=3, row=3)
but_eql.grid(column=4, row=3)
but_bra.grid(column=0, row=3)
but_bra2.grid(column=2, row=3)
class Function():
def __init__(self, text_variable):
# definingg variables for oparation functions
self.text_variable = text_variable
# defining the functions
def numb_press(self, numb):
self.text_variable.set(self.text_variable.get()+numb)
def clear(self):
self.text_variable.set("")
def delete(self):
temp = self.text_variable.get()
self.text_variable.set(str(temp[:-1]))
def eval (self):
temp = self.text_variable.get()
self.text_variable.set(str(eval(temp)))
if __name__ == '__main__':
app = Window((500,450),'app')
app.mainloop()
这是我的版本,修复了许多其他问题:
import tkinter as tk
from tkinter import ttk
from tkinter.messagebox import showwarning
from functools import partial
# Star imports are generally frowned upon
class Window(tk.Tk):
def __init__(self, size, title):
super().__init__()
self.geometry(f"{size[0]}x{size[1]}")
self.minsize(size[0], size[1])
self.title(title)
# "Globally" shared variable
self.text_var = tk.StringVar()
# The frames we'll be using; note the captial casing (Python standard)
self.display_frame = DisplayFrame(self, self.text_var)
self.button_frame = ButtonFrame(self, self.text_var)
class DisplayFrame(ttk.Frame):
"""Displays the current input"""
def __init__(self, parent, text_var):
super().__init__(master=parent)
self.pack(expand=True, fill='both', side='top')
self.entry_field = ttk.Entry(self, textvariable=text_var, state="readonly") # state="readonly" prevents the user from typing in whatever they want
self.entry_field.pack(expand=True, fill='both')
class ButtonFrame(ttk.Frame):
"""The input buttons"""
def __init__(self, parent, text_var):
super().__init__(master=parent)
self.parent = parent
self.text_variable = text_var
self.pack(side='bottom', expand=True, fill='both')
# Add the buttons with a loop
# Use `partial` due to how function binding works with a loop variable
num_buttons = [ttk.Button(self, text=str(i), command=partial(self.num_press, str(i))) for i in range(1, 10)] + [ttk.Button(self, text="0", command=lambda: self.num_press("0"))]
# Operation buttons
but_add = ttk.Button(self, text="+",command=lambda: self.num_press('+'))
but_sub = ttk.Button(self, text="-",command=lambda: self.num_press('-'))
but_mul = ttk.Button(self, text="*",command=lambda: self.num_press('*'))
but_div = ttk.Button(self, text="/",command=lambda: self.num_press('/'))
but_per = ttk.Button(self, text="%",command=lambda: self.num_press('%'))
but_bra = ttk.Button(self, text='(',command=lambda: self.num_press('('))
but_bra2 = ttk.Button(self, text=')',command=lambda: self.num_press(')'))
but_eql = ttk.Button(self, text="=", command=self.evaluate)
but_del = ttk.Button(self, text="DEL", command=self.delete)
but_clr = ttk.Button(self, text="CLR", command=self.clear)
# Grid the number buttons
for i in range(3):
for j in range(3):
num_buttons[3*i + j].grid(row=i, column=j)
num_buttons[-1].grid(row=3, column=1)
but_add.grid(column=3, row=0)
but_sub.grid(column=3, row=1)
but_mul.grid(column=3, row=2)
but_div.grid(column=4, row=0)
but_del.grid(column=4, row=1)
but_clr.grid(column=4, row=2)
but_per.grid(column=3, row=3)
but_eql.grid(column=4, row=3)
but_bra.grid(column=0, row=3)
but_bra2.grid(column=2, row=3)
def num_press(self, val):
"""Appends `val` to the current text variable value"""
self.text_variable.set(self.text_variable.get()+val)
def clear(self):
"""Resets the text variable"""
self.text_variable.set("")
def delete(self):
"""Removes the last character from the text variable"""
self.text_variable.set(self.text_variable.get()[:-1])
def evaluate(self):
"""Attemps to evaluate the string that's been entered"""
try:
self.text_variable.set(str(eval(self.text_variable.get()))) # NOTE: `eval` and `exec` can be dangerous - they run whatever code is given them!
except SyntaxError:
showwarning(title="Invalid command", message="The entered command is invalid")
if __name__ == '__main__':
app = Window((500, 450), 'app')
app.mainloop()