tkinter error. My callback is bypassing the try attempt and giving the except error message. Need calculations to work - tkinter-entry

Hello my callback appears not to be calculating the sales tax and amount due values and is throwing errors. New to tkinter and not sure if I am handling correctly when a button needs to handle multiple commands. Any help would be appreciated!
import tkinter as tk
class TkCalc:
def init(self):
self.main_window = tk.Tk()
self.main_window.title('Tax Calculator')
self.main_window.geometry('250x125')
self.line1_frame = tk.Frame(self.main_window)
self.line2_frame = tk.Frame(self.main_window)
self.line3_frame = tk.Frame(self.main_window)
self.line4_frame = tk.Frame(self.main_window)
self.line5_frame = tk.Frame(self.main_window)
self.purchase_label = tk.Label(self.line1_frame, text='Total Purchase:')
self.purchase_entry = tk.Entry(self.line1_frame, width=10)
self.purchase_label.pack(side='left')
self.purchase_entry.pack(side='left')
self.tax_label = tk.Label(self.line2_frame, text='Tax Rate: ')
self.tax_entry = tk.Entry(self.line2_frame, width=5)
self.tax_label.pack(side='left')
self.tax_entry.pack(side='left')
self.tax_label2 = tk.Label(self.line3_frame, text='Sales Tax: ')
self.tax_value = tk.StringVar()
self.tax_result_label = tk.Label(self.line3_frame, textvariable=self.tax_value)
self.tax_value.set('$ 0.00')
self.tax_label2.pack(side='left')
self.tax_result_label.pack(side='left')
self.amount_due = tk.Label(self.line4_frame, text='Amount Due: ')
self.amount_value = tk.StringVar()
self.amount_due_label = tk.Label(self.line4_frame, textvariable=self.amount_value)
self.amount_value.set('$ 0.00')
self.amount_due.pack(side='left')
self.amount_due_label.pack(side='left')
self.calc_tax_button = tk.Button(self.line5_frame, text='Calculate', command=self.show_tax_message)
self.quit_button = tk.Button(self.line5_frame, text='Quit', command=self.main_window.destroy)
self.calc_tax_button.pack(side='left')
self.quit_button.pack(side='left')
self.line1_frame.pack()
self.line2_frame.pack()
self.line3_frame.pack()
self.line4_frame.pack()
self.line5_frame.pack()
tk.mainloop()
def show_tax_message(self):
try:
purchase_amount = float(self.purchase_entry.get())
tax_amount = float(self.tax_value.get())
tax = purchase_amount * (tax_amount/100)
total = purchase_amount + tax
self.amount_value.set(f'${total:.2f}')
self.tax_value.set(f'${tax:.2f}')
except ValueError:
self.amount_value.set('Error')
self.tax_value.set('Error')
tk_calc = TkCalc()

Related

Python loop does not work accurately and reliably with time.sleep

What would be the best way to run a program once a day.
time.sleep is inaccurate on long runs.
I try to get def send_stock_data (self): run once a day, for example. time.sleep drifts too much for this purpose.
The program reads the excel file and sends the data by e-mail if the column 'Amount' is 0.
class progloop():
def prog_loop (self):
progress.pack_forget()
while run_cycle == True:
get_stock_and_send_mail()
sleep(48000)
continue
def __init__(self):#adds Threading to loop
t = threading.Thread(target=self.prog_loop)
t.start()
The above class currently handles the loop.
Below is the full script.
import threading
import tkinter as tk
import os
import smtplib
import datetime
import time
import pandas as pds
import traceback
import warnings
warnings.simplefilter(action='ignore', category=FutureWarning)
from tkinter import BOTTOM,HORIZONTAL, Label, Menu, PhotoImage, messagebox, filedialog, ttk
from datetime import datetime
from time import sleep
root = tk.Tk()
sec = 0
action = None
run_cycle = True
stop_cycle = True
today = datetime.now()
clock_time = today.strftime('%H:%M:%S')
date = today.strftime('%d/%m/%Y')
weekday = datetime.today().strftime('%A')
def on_run():#start send_stock_data loop and timer
global run_cycle, action
global action
string_var.set('Application state: Running')
run_cycle = True
if not action:
timer()
def on_stop():#pause send_stock_data loop and timer
global run_cycle, action
string_var.set('Application state: Paused')
run_cycle = False
messagebox.showinfo('Attention','Program is paused, press Run to resume execution')
if action:
root.after_cancel(action)
action = None
def Info():#Info btn data
messagebox.showinfo('Application info','''-The application reads the stock balance from the excel file and sends out e-mail information if the part (s)
of the warehouse balance has run out of stock within the alarm limit.\n
-The default path to the excel file is specified in the Windows environment variables as 'FilePath'\n
-In case of problems contact the author
\n\nDefault alarm limit = 0 parts in stock
\n\nDefault Google smtp server:'smtp.gmail.com'\nDefault port: 587 ''')
def write_err_log():#writes an error log with traceback
traceback_err = traceback.format_exc()
date_time = [clock_time,date]
write_log = open("ErrorLog.txt", "a")
write_log.write(str(date_time)) and write_log.write(str(traceback_err))
write_log.close()
#Gui
string_var = tk.StringVar()
string_var.set('Application state: Waiting for commands')
root.iconbitmap(r'C:\\Users\\Lauri\\Visual_studio\\Bitmap_2.ico')
root.title('Warehouse assistant')
root.geometry('460x360')
root.resizable(False,False)
background_image = PhotoImage(file = r'C:\\Users\\Lauri\\Visual_studio\\BcImage.png')
background_label = tk.Label(image=background_image)
background_label.place(x=0, y=0, relwidth=1, relheight=1)
Label_header = ttk.Label(root, font=('underline', 12),text='Parts balance monitoring application').pack()
Label_start = ttk.Label(root,font=('underline',8), text='Press Run to start the application\nPress Pause to stop the application').pack()
Label_appState = ttk.Label(root, font=('underline', 10),textvariable=string_var).pack()
btnInfo = ttk.Button(root, text = 'Info', width= 15, command = Info).pack()
Start_btn = ttk.Button(root, text = 'Run', width= 15, command=lambda:[bar(),progloop(),root.after(1000,on_run())]).pack()
Stop_btn = ttk.Button(root, text = 'Pause', width= 15, command = on_stop).pack()
exit_btn = ttk.Button(root, text = 'Exit', width= 25, command =lambda:[root.after(1000,),root.destroy()]).pack(side=BOTTOM)
menu = Menu(root)
root.config(menu=menu)
contact_num = os.environ.get('Contact_number')
contact_email = os.environ.get('Contact_email')
helpmenu = Menu(menu)
menu.add_cascade(label='Contact', menu=helpmenu)
helpmenu.add_command(label=contact_email)
helpmenu.add_command(label=contact_num)
helpmenu.add_command(label= 'Exit', command=root.destroy)
progress = ttk.Progressbar(root, orient = HORIZONTAL,length = 158, mode = 'determinate')
def bar():#progressbar
progress['value'] = 5
root.update_idletasks()
root.after(50)
progress['value'] = 43
root.update_idletasks()
root.after(300)
progress['value'] = 68
root.update_idletasks()
root.after(50)
progress['value'] = 100
root.update_idletasks()
root.after(1)
progress.pack(side=BOTTOM)
class get_stock_and_send_mail: #send inventory balance information by email
def send_stock_data(self):
count = 0
pds.set_option('display.max_colwidth', -1)
pds.set_option('colheader_justify','left')
#reads excel file and searches for desired inventory balance value
while True:
file = os.environ.get('FilePath')#default path to file specified in the Windows environment variables as 'FilePath'
try:
dataFrame = pds.read_excel(file)
break
except PermissionError as error:
write_err_log()
messagebox.showerror(title='error',message= 'Permission Error Permission error has occured during read file?\n\n\n'+str(error)+"'.",
detail=traceback.format_exc())
except FileNotFoundError as error:
messagebox.showwarning(title='Select Excel File',
message='DEFAULT FILE NOT FOUND.\nChoose Excel file from directory.\nCONTINUE --> PRESS OK')
file = filedialog.askopenfilename()#manual path to file if default path doesn't exist
try:
dataFrame = pds.read_excel(file)
break
except FileNotFoundError:
write_err_log()
continue
df_bool = []
for Amount in dataFrame.Amount:
if Amount <= 0:
df_bool.append(True)
else:
df_bool.append(False)
if True in df_bool:
while run_cycle == True:
today = datetime.now()
clock_time = today.strftime('%H:%M:%S')
date = today.strftime('%d/%m/%Y')
weekday = datetime.today().strftime('%A')
Email_adress = os.environ.get('email_user')
Email_password = os.environ.get('email.password')
empty_stock = dataFrame.loc[dataFrame.Amount <= 0]
try:
with smtplib.SMTP('smtp.gmail.com',587) as server:
server.ehlo()
server.starttls()
server.ehlo_or_helo_if_needed()
server.set_debuglevel(1)
server.login(Email_adress,Email_password)
subject = 'no-reply'
body = f"""Row no.:{empty_stock}\nPart (s) is out of stock\n
Date: {weekday} {date}\n
Time: {clock_time}
\n\n\nThis was an automatically generated message.\nDo not reply to this message!
"""
msg = f'subject:{subject}\n\n{body}'
server.sendmail(Email_adress,Email_adress, msg)
server.quit
except smtplib.SMTPException as error:
write_err_log()
count +=1
if count <= 5:
continue
elif count >= 6:
messagebox.showerror(title='error',message= 'ERROR'+str(error)+"'.",
detail=traceback.format_exc())
break
def __init__(self):#adds Threading to loop
t = threading.Thread(target=self.send_stock_data)
t.start()
class progloop():
def prog_loop (self):
progress.pack_forget()
while run_cycle == True:
get_stock_and_send_mail()
sleep(48000)
continue
def __init__(self):#adds Threading to loop
t = threading.Thread(target=self.prog_loop)
t.start()
def timer(): #Runtime timer
global sec
if run_cycle == False:
return
sec += 1
time['text'] = f'Runtime: {sec} sec'
time.after(1000, timer)
time = Label(root, fg='black')
time.pack(side=BOTTOM)
root.mainloop()
If you really want to actually use a sleep, and time shifting/drifting over multiple days is the problem, what you can do, although not perfectly accurate, is to readjust the sleep time based on current time. Something like :
def seconds_since_midnight():
now = datetime.now()
return (now - now.replace(hour=0, minute=0, second=0, microsecond=0)).total_seconds()
def one_day_to(day_time_secs):
return 86400+day_time_secs-seconds_since_midnight()
And using for instance
sleep(one_day_to(3600*18))
to schedule at about 18h00 the next day, without drifting from day to day

I cant see a problem but unexpected unindent occurs in my tkinter program

def login():
#clean
Ename.delete(0,'end')
Eage.delete(0,'end')
Epswrd.delete(0,'end')
Everpass.delete(0,'end')
root.destroy()
#/clean
stem = Tk()
stem.geometry("810x450")
stem.resizable(0,0)
stem.title("Log in")
approve1 = ""
approve2 = ""
#function
#player 1
def player1():
name1 = Ename1.get()
pswrd1 = Epswrd1.get()
if (name1 == "") or (pswrd1==""):
messagebox.showinfo("Invalid", "Please enter a username or password")
else:
conn = mariadb.connect(
user="root",password="",
host="localhost",
database="chessdatabase")
cur = conn.cursor()
#insert information
try:
cur.execute("SELECT User,Password from players where User=?, and Password = ?",(name1,pswrd1))
row = cur.fetchone()
if row==None:
messagebox.showinfo("Error" , "Invalid User Name And Password")
else:
approve1 = p1login
conn.commit()
#/player 1
#/function
#display
title1 = Label(stem, text="Touch-Move Tkinter Chess", font=("Colonna MT", 35))
title1.place(x=140, y=40)
#player 1 display
name1 = Label(stem, text="Player 1", font=("Georgia", 13))
name1.place(x=50, y=175)
Ename1 = Entry(stem, font=("Georgia", 11), width=17)
Ename1.place(x=150, y=175)
The error occurs at the left side indent of title1 = Label(stem, text="Touch-Move Tkinter Chess", font=("Colonna MT", 35)), Why does it make "unexpected unindent" error?
I've encountered the same problem before but for some reason it was fixed. Sorry I'm new to python so I don't really know much about indents in programming

Unable to insert data in Listbox of tkinter

I'm using "on_message" function which is called in receiveText() function to receive an incoming message from MQTT server.
The message which is being received is getting reflected in the print statement but unable to get insert in the Listbox.
While using the same lines of code, it is getting inserted in sendText() function.
Code:
class chat_UI:
def __init__(self, roots, nameLogin, friendLogin):
roots.title("Chat window")
self.nameLogin = nameLogin
self.friendLogin = friendLogin
self.scrollbar = Scrollbar(roots) # To see through previous messages.
self.msg_list = Listbox(roots, height=30, width=100, yscrollcommand=self.scrollbar.set)
self.msg_list.grid(row=0, column=0, columnspan=1)
self.scrollbar.grid(sticky = W)
self.msg_list.grid(sticky = E)
#self.msg_list.see(END)
Label(roots, text="Enter Message").grid(row=1,column=0)
self.entry_field = Entry(roots,width=20)
self.entry_field.grid(row=1, column=1)
self.sendB = Button(roots, text='Send', command=self.sendText)
self.sendB.grid(row=2, column = 1, pady=4, sticky=W)
t1 = threading.Thread(target=self.recieveText,args=(friendLogin, nameLogin))
t1.start()
#t1.join()
def sendText(self):
nameLogin = self.nameLogin
friendLogin = self.friendLogin
self.message = self.entry_field.get()
#self.msg_list.insert(END, (self.friendLogin + ": " + recMsg))
self.msg_list.insert(END, (self.nameLogin + ": " + self.message))
mqtt_connect(nameLogin).publish(("techieChat/" + nameLogin), str(self.message), qos = 0)
def on_message(client, userdata, msg):
print("In on messafe fn")
global recMsg
recMsg = str(msg.payload)
print("message in chat_ui on_mesg fn: " + recMsg)
self.msg_list.insert(END, recMsg)
def recieveText(self, friendLogin, nameLogin):
print("message in receive text message: " + recMsg)
client = mqtt_connect(friendLogin)
client.subscribe("techieChat/" + friendLogin)
client.on_message = chat_UI.on_message
The chat_UI class is being instantiated from other class
self.newWindow = Toplevel(self.roots)
chat_UI(self.newWindow, nameLogin, friendLogin)
Have you tried to use a tk label? They can offer variable information like so:
label = tk.Label(textvariable=recMsg)
label.pack(side="left") #<--- i presume you may want to use grid here

PyQT Threadin kills my memory

The following block of code is part of the class Dataview(QWidget), which is called in main.py. It creates 3 tables; bids, asks and history and automaticly fetches data from various exchanges via API.
The application works, but when viewing in Task Manager my memory usage keeps getting bigger and bigger - which I think is due to way I run these threads. What am I doing wrong here?
EDIT:
MAIN.PY
import sys
from PyQt4 import QtCore, QtGui, Qt
from datetime import datetime
import time
import thread
from apis import API_Bitstamp_usd
class Dataview(QtGui.QFrame):
def __init__(self, parent=None):
QtGui.QWidget.__init__(self, parent)
self.setFixedSize(152,730)
self.setStyleSheet('background: #444;background-color: QLinearGradient(x1:0, y1:0,x2:0, y2:1,stop:1 #212121,stop:0.4 #343434/*,stop:0.2 #343434,stop:0.1 #ffaa00*/);margin-bottom:-1px;padding-bottom:1px;')
self.setup_table_asks()
self.setup_table_bids()
self.setup_table_hist()
self.setup_label()
self.start_threads()
def setup_table_asks(self):
self.table_asks = QtGui.QTableWidget(self)
self.table_asks.setGeometry(10,30,132,180)
self.table_asks.setStyleSheet('color: lightblue; background: #444;background-color: QLinearGradient(x1:0, y1:0,x2:0, y2:1,stop:1 #212121,stop:0.4 #343434/*,stop:0.2 #343434,stop:0.1 #ffaa00*/);margin-bottom:-1px;padding-bottom:1px;')
self.table_asks.setFrameShadow(QtGui.QFrame.Raised)
self.table_asks.horizontalHeader().hide()
self.table_asks.verticalHeader().hide()
self.table_asks.setHorizontalScrollBarPolicy(QtCore.Qt.ScrollBarAlwaysOff)
self.table_asks.setVerticalScrollBarPolicy(QtCore.Qt.ScrollBarAlwaysOff)
self.table_asks.setEditTriggers(QtGui.QAbstractItemView.NoEditTriggers)
self.table_asks.setSelectionMode(QtGui.QAbstractItemView.NoSelection)
self.table_asks.setShowGrid(False)
self.table_asks.setRowCount(300)
self.table_asks.setColumnCount(3)
self.table_asks.setColumnWidth(0,50)
self.table_asks.setColumnWidth(1,40)
self.table_asks.setColumnWidth(2,40)
self.table_asks.setCursor(QtCore.Qt.SizeVerCursor)
self.table_asks.scrollToBottom()
def setup_table_bids(self):
self.table_bids = QtGui.QTableWidget(self)
self.table_bids.setGeometry(10,230,132,180)
self.table_bids.setStyleSheet('color: lightblue; background: #444;background-color: QLinearGradient(x1:0, y1:0,x2:0, y2:1,stop:1 #212121,stop:0.4 #343434/*,stop:0.2 #343434,stop:0.1 #ffaa00*/);margin-bottom:-1px;padding-bottom:1px;')
self.table_bids.setFrameShadow(QtGui.QFrame.Raised)
self.table_bids.horizontalHeader().hide()
self.table_bids.verticalHeader().hide()
self.table_bids.setHorizontalScrollBarPolicy(QtCore.Qt.ScrollBarAlwaysOff)
self.table_bids.setVerticalScrollBarPolicy(QtCore.Qt.ScrollBarAlwaysOff)
self.table_bids.setEditTriggers(QtGui.QAbstractItemView.NoEditTriggers)
self.table_bids.setSelectionMode(QtGui.QAbstractItemView.NoSelection)
self.table_bids.setShowGrid(False)
self.table_bids.setRowCount(300)
self.table_bids.setColumnCount(3)
self.table_bids.setColumnWidth(0,50)
self.table_bids.setColumnWidth(1,40)
self.table_bids.setColumnWidth(2,40)
self.table_bids.setCursor(QtCore.Qt.SizeVerCursor)
def setup_table_hist(self):
self.table_hist = QtGui.QTableWidget(self)
self.table_hist.setGeometry(10,414,132,206)
self.table_hist.setStyleSheet('color: lightblue;background: #444;background-color: QLinearGradient(x1:0, y1:0,x2:0, y2:1,stop:1 #212121,stop:0.4 #343434/*,stop:0.2 #343434,stop:0.1 #ffaa00*/);margin-bottom:-1px;padding-bottom:1px;')
self.table_hist.setFrameShadow(QtGui.QFrame.Raised)
self.table_hist.horizontalHeader().hide()
self.table_hist.verticalHeader().hide()
self.table_hist.setHorizontalScrollBarPolicy(QtCore.Qt.ScrollBarAlwaysOff)
self.table_hist.setVerticalScrollBarPolicy(QtCore.Qt.ScrollBarAlwaysOff)
self.table_hist.setEditTriggers(QtGui.QAbstractItemView.NoEditTriggers)
self.table_hist.setSelectionMode(QtGui.QAbstractItemView.NoSelection)
self.table_hist.setShowGrid(False)
self.table_hist.setRowCount(150)
self.table_hist.setColumnCount(3)
self.table_hist.setColumnWidth(0,45)
self.table_hist.setColumnWidth(1,45)
self.table_hist.setColumnWidth(2,40)
self.table_hist.setCursor(QtCore.Qt.SizeVerCursor)
def setup_label(self):
self.label = QtGui.QLabel(self)
self.label.setGeometry(10,210,132,20)
self.label.setFrameShadow(QtGui.QFrame.Sunken)
self.label.setText('last_price')
self.label.setStyleSheet('color: lightblue;background: #444;background-color: QLinearGradient(x1:0, y1:0,x2:0, y2:1,stop:1 #212121,stop:0.4 #343434/*,stop:0.2 #343434,stop:0.1 #ffaa00*/);margin-bottom:-1px;padding-bottom:1px;')
self.label.setAlignment(QtCore.Qt.AlignCenter)
self.title = QtGui.QLabel(self)
self.title.setGeometry(10,10,132,20)
self.title.setStyleSheet('color: silver;background: #444;background-color: QLinearGradient(x1:0, y1:0,x2:0, y2:1,stop:1 #212121,stop:0.4 #343434/*,stop:0.2 #343434,stop:0.1 #ffaa00*/);margin-bottom:-1px;padding-bottom:1px;')
self.title.setText('Bitstamp')
self.title.setAlignment(QtCore.Qt.AlignCenter)
def start_threads(self):
thread.start_new_thread(self.fill_table_bids, ())
thread.start_new_thread(self.fill_table_asks, ())
thread.start_new_thread(self.fill_table_hist, ())
def fill_table_bids(self):
while True:
ticker = API_Bitstamp_usd()
x = ticker.get_depth()
bids = x[0]
row = 0
depth = 0
for i in bids:
price = i[0]
qty = i[1]
depth = format(float(depth) + float(qty), '.1f')
self.table_bids.setRowHeight(row, 12)
tw = QtGui.QTableWidgetItem(str(price))
self.table_bids.setItem(row,0,tw)
tw = QtGui.QTableWidgetItem(str(qty))
tw.setTextAlignment(5)
self.table_bids.setItem(row,1,tw)
tw = QtGui.QTableWidgetItem(str(depth))
tw.setTextAlignment(5)
self.table_bids.setItem(row,2,tw)
row = row + 1
time.sleep(2)
def fill_table_asks(self):
while True:
ticker = API_Bitstamp_usd()
x = ticker.get_depth()
asks = x[1]
row = 0
depth = 0
for i in asks[:300]:
depth = depth + float(i[1])
for i in reversed(asks[:300]):
price, qty = i[0], i[1]
depth = format(float(depth) - float(qty), '.1f')
self.table_asks.setRowHeight(row, 12)
tw = QtGui.QTableWidgetItem(str(price))
self.table_asks.setItem(row,0,tw)
tw = QtGui.QTableWidgetItem(str(qty))
tw.setTextAlignment(5)
self.table_asks.setItem(row,1,tw)
if depth > 0:
tw = QtGui.QTableWidgetItem(str(depth))
tw.setTextAlignment(5)
self.table_asks.setItem(row,2,tw)
row = row + 1
time.sleep(2)
def fill_table_hist(self):
while True:
ticker = API_Bitstamp_usd()
x = ticker.get_history()
row = 0
for i in x:
timestamp = datetime.fromtimestamp(float(i[0])).strftime('%H:%M:%S')
price = i[1]
qty = i[2]
type = i[3]
self.table_hist.setRowHeight(row, 12)
tw = QtGui.QTableWidgetItem(str(timestamp))
self.table_hist.setItem(row,0,tw)
tw = QtGui.QTableWidgetItem(str(price))
tw.setTextAlignment(5)
self.table_hist.setItem(row,1,tw)
tw = QtGui.QTableWidgetItem(str(qty))
tw.setTextAlignment(5)
if type == 'sell':
tw.setTextColor(QtGui.QColor('red'))
else:
tw.setTextColor(QtGui.QColor('green'))
self.table_hist.setItem(row,2,tw)
row = row + 1
self.label.setText(str(x[0][1]))
time.sleep(2)
if __name__ == "__main__":
app = QtGui.QApplication(sys.argv)
myapp = Dataview()
myapp.show()
sys.exit(app.exec_())
APIS.PY
import urllib2
import json
class API_Bitstamp_usd:
def __init__(self):
self.url = 'https://www.bitstamp.net/api/'
def get_depth(self):
try:
url = self.url + 'order_book/'
json_obj = urllib2.urlopen(url)
data = json.load(json_obj)
asks_, bids_ = [], []
for i in data['bids']:
price, qty = format(float(i[0]), '.2f'), format(float(i[1]), '.2f')
bids_.append([float(price), float(qty)])
for i in data['asks']:
price, qty = format(float(i[0]), '.2f'), format(float(i[1]), '.2f')
asks_.append([float(price), float(qty)])
return bids_, asks_
except:
pass
def get_history(self):
try:
url = self.url + 'transactions/'
json_obj = urllib2.urlopen(url)
data = json.load(json_obj)
history_ = []
for i in data:
timestamp, price, amount, type = i['date'], format(float(i['price']), '.3f'), format(float(i['amount']), '.2f'), ''
history_.append([timestamp, float(price), float(amount), type])
return history_
except:
pass

How can I incorporate an input limit of 999 in my calculator script?

I am aware this is a duplicate from a past thread, but when I use that suggestion, it says 'unindent does not match any outer indentation level'. When I run the script at school (this is a school assignment) a blank GUI appears with no buttons, and when I run it at home, it appears with the error message as above- I am using Python 3.3.2 on each computer. The code for the 999 limit is in lines 45-57 and the error message appears on the first line (45). I'm quite new to python and my teacher is awful, so apologies if my question sounds quite silly. Can I have a suggestion as to how to get this to work?
Thanks a lot!
from tkinter import *
class Calculator(Frame):
def frame(this, side):
w = Frame(this)
w.pack(side=side, expand=YES, fill=BOTH)
return w
def button(this, root, side, text, command=None):
w = Button(root, text=text, command=command)
w.pack(side=side, expand=YES, fill=BOTH)
return w
need_clr = False
def digit(self, digit):
if self.need_clr:
self.display.set('')
self.need_clr = False
self.display.set(self.display.get() + digit)
def sign(self):
need_clr = False
cont = self.display.get()
if len(cont) > 0 and cont[0] == '-':
self.display.set(cont[1:])
else:
self.display.set('-' + cont)
def oper(self, op):
self.display.set(self.display.get() + ' ' + op + ' ')
self.need_clr = False
def calc(self):
try:
self.display.set(eval(self.display.get()))
self.need_clr = True
except:
showerror('Operation Error', 'Illegal Operation')
self.display.set('')
self.need_clr = False
def calc(self):
try:
self.display.set(self.validate_result(eval(self.display.get())))
self.need_clr = True
except:
showerror('Operation Error', 'Illegal Operation')
self.display.set('')
self.need_clr = False
def validate_result(self, result):
if result >= 1000:
raise ValueError('result too big!')
else:
return result
def __init__(self):
Frame.__init__(self)
self.option_add('*Font', 'Dotum 15')
self.pack(expand=YES, fill=BOTH)
self.master.title('Simple Calculator')
self.display = StringVar()
e = Entry(self, relief=SUNKEN, textvariable=self.display)
e.pack(side=TOP, expand=YES, fill=BOTH)
for key in ("123", "456", "789"):
keyF = self.frame(TOP)
for char in key:
self.button(keyF, LEFT, char,
lambda c=char: self.digit(c))
keyF = self.frame(TOP)
self.button(keyF, LEFT, '0', lambda ch='0': self.digit(ch))
opsF = self.frame(TOP)
for char in "+-=":
if char == '=':
btn = self.button(opsF, LEFT, char, self.calc)
else:
btn = self.button(opsF, LEFT, char,
lambda w=self, s=char: w.oper(s))
clearF = self.frame(BOTTOM)
self.button(clearF, LEFT, 'Clr', lambda w=self.display: w.set(''))
if __name__ == '__main__':
Calculator().mainloop()

Resources