Python Tkinter:无法制作计算器项目

问题描述 投票:0回答:1

我正在使用带有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()
python-3.x oop tkinter
1个回答
0
投票

这里有几个错误。

  1. 您在绑定
    buttons
    delete
    clear
    eval
    属性之前调用
    Frame_Buttons
    。因此,当实例化 
    but_eql
     时,它会失败,因为还没有 
    self.eval
    。如果您将该调用移到最后,您就可以让它运行。
  2. 您的代码设置有点奇怪/迂回。这是一个以最小的更改修复了逻辑的版本:
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()
    
© www.soinside.com 2019 - 2024. All rights reserved.