2013-03-29 5 views
1

Я пытаюсь сделать простое приложение калькулятора с помощью Tkinter, но каждый раз, когда я запускаю этот код я получаю сообщение об ошибке, говорящееPython 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 

КОД:

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 и не понимаю, почему линия «resolved = eval (выражение)» не работает. пожалуйста, помогите

ответ

2

Итак, причина, по которой eval не работает, заключается в том, что при первом запуске вашей программы expression - это просто пустая строка. Если вы перейдете к оболочке python и введите eval(''), вы увидите ту же ошибку.

Одно решение было бы проверить, если expression пустая строка или нет, и сделать что-то вроде этого:

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

Однако, даже после применения этого исправления, ваша программа не будет работать, для несвязанный причины. Основная причина заключается в том, что вы никогда не вызываете tk.mainloop() (или как бы там ни называлось), поэтому окно не будет отображаться.

Это из-за вашей петли while. Вы хотели бы постоянно проверять поле ввода и обновлять свой холст всякий раз, когда вы получаете новый ввод после запуска через eval.

Однако программы GUI, в общем, не работают таким образом, и при их написании требуют иного подхода и подхода. Вместо написания циклов для проверки и обновления состояния программы вы записываете функции, которые будут автоматически вызываться всякий раз, когда изменяется состояние программы (которые называются событиями). Сначала это будет немного назад, но со временем это поможет сделать ваш код более чистым и простым в управлении.

Вы на самом деле уже делаете это в одной части своей программы - с помощью функции exitbtn. Теперь вам просто нужно преобразовать петлю while в аналогичную функцию и привязать ее к объекту Entry.

EDIT:

Вот пример кода, который делает то, что вы хотите:

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> событий).
+0

Что вы имеете в виду? у вас есть простой пример, на который я мог бы лучше понять? – user2155059

+0

@ user2155059 - Я добавил пример кода – Michael0x2a

+0

, где вы определили tk.mainloop? – user2155059

Смежные вопросы