Python Tkinter Calculator不会评估条目小部件中的文本

时间:2013-03-29 15:11:15

标签: python tkinter eval calculator

我正在尝试使用tkinter创建一个简单的计算器应用程序,但每次我运行下面的代码时都会收到错误消息

Traceback (most recent call last):
  File "C:\Python33\Lib\site-packages\pythonwin\pywin\framework\scriptutils.py", line 326, in RunScript
    exec(codeObject, __main__.__dict__)
  File "C:\Users\csp\Python\Calculator App.py", line 17, in <module>
    solved = eval(expression)
  File "<string>", line 0

   ^
SyntaxError: unexpected EOF while parsing

CODE:

from tkinter import *
tk = Tk()
tk.title('Calculator')
inp = Entry(tk,text="Enter Expression Here",width=20)
inp.pack()
exit = False
def exitbtn():
    global exit
    exit = True
    return exit
btn = Button(tk,text="Quit?",command=exitbtn)
btn.pack
canvas = Canvas(tk,width=200,height=200)
canvas.pack()
while not exit:
    expression = inp.get()
    solved = eval(expression)
    canvas.create_text(100,100,text=expression,font=('Times', 15))
    canvas.create_text(100,150,text=solved,font=('Times', 15))
    if exit == True:
        break
tk.destroy()

我是Python的新手,并且不明白为什么“solve = eval(expression)”行无效。请帮忙

1 个答案:

答案 0 :(得分:2)

因此,eval无效的原因是因为当您第一次启动程序时,expression只是一个空字符串。如果你转到python shell并输入eval(''),你会看到同样的错误。

一种解决方案是检查expression是否为空字符串,并执行以下操作:

expression = inp.get()
if expression != '':
    solved = eval(expression)
else:
    solved = '?'

但是,即使您应用此修复程序,您的程序也无法正常工作。主要原因是你永远不会调用tk.mainloop()(或其他任何名称),因此窗口不会显示。

这是因为你的while循环 - 你想要做的是不断检查输入字段并在通过eval运行后获得新输入时更新画布。

然而,GUI程序通常不会以这种方式工作,并且在编写它们时需要不同的思维方式和方法。您可以编写将在程序状态更改时自动调用的函数(称为事件),而不是编写循环来检查和更新程序状态。起初它会感觉有点倒退,但随着时间的推移它会帮助您使代码更清晰,更易于管理。

您实际上已经在程序的某个部分执行此操作 - 使用exitbtn功能。现在,您只需要将while循环转换为类似的函数并将其绑定到Entry对象。

修改

以下是一些可以满足您需求的示例代码:

import sys
from tkinter import *


# Create the GUI
tk = Tk()
tk.title('Calculator')

inp = Entry(tk, text="Enter Expression Here", width=20)
inp.pack()

btn = Button(tk, text="Quit?")
btn.pack()

canvas = Canvas(tk, width=200, height=200)
canvas.pack()


# Create callback functions
def end_program(event):
    '''Destroys the window and ends the program without needing
    to use global variables or a while loop'''
    tk.destroy()
    sys.exit() # Automatically ends any Python program

def update_canvas(event):
    '''Gets the input, tries to eval it, and displays it to the canvas'''
    expression = inp.get()
    try:
        solved = eval(expression)
    except SyntaxError: 
        # The expression wasn't valid, (for example, try typing in "2 +")
        # so I defaulted to something else.
        solved = '??'

    canvas.delete('all') # remove old text to avoid overlapping
    canvas.create_text(100, 100, text=expression,font=('Times', 15))
    canvas.create_text(100, 150, text=solved,font=('Times', 15))


# Bind callbacks to GUI elements
btn.bind('<Button-1>', end_program)
inp.bind('<KeyRelease>', update_canvas)


# Run the program
tk.mainloop()

有些注意事项:

  • 我移动了代码以检查inp并将画布写入update_canvas函数,并删除了while循环。
  • 只要有人在键入update_canvas对象(inp事件)时放下键,就会自动调用<KeyRelease>函数。
    • 这可能会导致一些问题 - 这意味着当用户正在向您的计算器输入文本时,将调用update_canvas函数。例如,如果用户键入2 + 2 *该怎么办?它不是一个完整的表达式,因此无法由eval解析。
    • 为了解决这个问题,我只是尝试将eval包裹起来,以防止任何错误输入破坏程序。
  • 同样,只要有人左键点击end_program对象(btn事件),就会调用<Button-1>