Related
I was making a vocab test program and I was making a grading button. But I faced a problem that when I press the grading twice, grade, entries, right, wrong keeps appends and I can't find the way to reset these lists. So, when I press the grade button again after I correct the answer, the grading overlaps and makes an error.
import tkinter
from tkinter import *
window = tkinter.Tk()
container = tkinter.Frame(window)
canvas = tkinter.Canvas(container)
window.title('Rescue word test')
window.geometry('640x480')
window.resizable(True, True)
scrollbar = tkinter.Scrollbar(container, orient="vertical", command=canvas.yview)
#scroll
main_frame = Frame(window)
main_frame.pack(fill=BOTH, expand=1)
my_canvas = Canvas(main_frame)
my_canvas.pack(side=LEFT, fill=BOTH, expand=1)
my_scrollbar = tkinter.Scrollbar(main_frame, orient=VERTICAL, command=my_canvas.yview)
my_scrollbar.pack(side=RIGHT, fill=Y)
my_canvas.configure(yscrollcommand=my_scrollbar.set)
my_scrollbar.bind('<Configure>', lambda e: my_canvas.configure(scrollregion= my_canvas.bbox("all")))
second_frame = Frame(my_canvas)
my_canvas.create_window((0,0), window= second_frame, anchor="nw")
def mouse_scroll(event):
my_canvas.yview_scroll(-1 * int((event.delta / 120)), "units")
my_canvas.bind_all("<MouseWheel>", mouse_scroll)
def getEntry( i ):
return list( second_frame.children.values() )[ i ]
Day21_eng = ['exquisite', 'acquisition', 'regulate', 'transportation', 'insight', 'straightforward', 'cultivate', 'innovation', 'preserve', 'odor', 'exception', 'munch', 'proclaim', 'slap', 'variability', 'investigate', 'flare', 'outpace', 'genuine', 'plead', 'fossilize', 'toil', 'drastic', 'withhold', 'inanimate', 'clockwise', 'amnesia', 'revive', 'theorize', 'culprit', 'limp', 'worn-out', 'indignity', 'span', 'bribe']
Day21_kor = [['우아한', '정교한', '절묘한'], ['취득', '획득', '습득'], ['규제하다', '통제하다'], ['운송', '운임', '추방'], ['통찰', '통찰력'], ['명확한', '솔직한'], ['경작하다', '기르다', '장려하다', '육성하다'], ['혁신'], ['보전', '보호지', '보호하다', '보존하다'], ['냄새', '악취', '기미', '낌새'], ['예외'], ['우적우적 먹다'], ['선언하다'], ['찰싹 때리다'], ['변화성', '가변성', '변용성'], ['조사하다'], ['불끈 성나게 하다', '이글거리다', '불꽃', '타오름'], ['앞지르다', '속도가 더 빠르다'], ['진짜의', '진품의'], ['탄원하다', '변호하다', '애원하다'], ['고착화하다', '화석화하다'], ['수고', '노고', '힘들게 일하다'], ['급격한', '극단적인'], ['보류하다', '유보하다'], ['생명 없는', '무생물의'], ['시계방향으로'], ['기억상실'], ['부활시키다', '되살아나게 하다'], ['이론화하다'], ['죄인', '범죄자', '장본인'], ['절뚝거리다', '느릿느릿 가다', '기운이 없는','축 처진'], ['닳아빠진', '진부한', '지친'], ['모욕', '무례', '치욕'], ['기간', '폭', '범위', '걸치다', '이르다'], ['뇌물을 주다', '뇌물']]
entries = []
grade =[]
def check():
for i, e in enumerate(entries):
value = e.get()
grade.append(str(value in Day21_kor[i]))
right = [i for i, value in enumerate(grade) if value == 'True']
wrong = [k for k, value in enumerate(grade) if value == 'False']
print(right) # I can check that these lists keep appends
print(wrong)
print(entries)
print(grade)
r = 0
for i in range(0, len(right)):
label_right = Label(second_frame, text='O', fg='Blue')
label_right.grid(column=3, row= right[r])
r += 1
w = 0
for i in range(0, len(wrong)):
label_wrong = Label(second_frame, text='X', fg= 'red')
label_wrong.grid(column=3, row= wrong[w])
w += 1
b = 0
for row, item in enumerate(Day21_eng):
global label_word
label_word = tkinter.Label(second_frame, text= item)
label_word.grid(column=0, row=row)
b += 1
#입력 값 35개
entry = tkinter.Entry(second_frame, width=30)
entry.grid(row=row, column=1, sticky='nsew')
# important to bind each one for access
entry.bind('<Return>', getEntry)
entries.append(entry) # save 'entry' into list
b_check = tkinter.Button(second_frame, text='grade', command=check)
b_check.grid(columnspan=2, row=36)
window.mainloop()
How can I reset these lists so I can re-grade the answers? I've tried adding right=[] wrong=[] entries=[] grade=[] and also used another list to get rid of the overlapped values in the list,
def check():
for i in range(0,35):
test_try_list[test_try].append(entry) # save 'entry' into list
for i, e in enumerate(test_try_list[test_try]):
value = e.get()
i_list.append(i)
print(i_list)
if len(i_list) > 35:
for i in range(0, len(i_list)):
new_i_list.append(i_list[i] % 35)
for v in new_i_list:
if v not in new_i_list2:
new_i_list2.append(v)
print(new_i_list2)
but it still doesn't work. How can I make button to re-grade?
You can use grade.clear() to clear list
def check():
grade.clear()
or you have to use global to inform function that it has to assign new list to external/global variable
def check():
global grade
grade = []
But I would run it without all these lists
def check():
correct = 0
wrong = 0
for i, (e, expected) in enumerate(zip(entries, Day21_kor)):
value = e.get()
if value in expected:
correct += 1
label = Label(second_frame, text='O', fg='Blue')
else:
wrong += 1
label = Label(second_frame, text='X', fg= 'red')
label.grid(column=3, row=i)
percent = correct/(correct+wrong)
print('Correct:', correct, '| Wrong:', wrong, '| Percent: {:.1%}'.format(percent))
Result:
Correct: 0 | Wrong: 35 | Percent: 0.0%
Correct: 1 | Wrong: 34 | Percent: 2.9%
I'm writing a program where the user will make a selection based on a target image. I'm trying to get the program to remove the selection buttons and wait 2 seconds after updating the target image before the selection choices are re-presented. The code that I have seems to "disable" the clicked button for 2 seconds, but does not remove either button.
from tkinter import *
import random
root = Tk()
root.geometry("500x500")
def click_b(event):
btn_b.pack_forget()
btn_c.pack_forget()
new_a()
root.update()
root.after(2000, show_btns())
def click_c(event):
btn_b.pack_forget()
btn_c.pack_forget()
new_a()
root.update()
root.after(2000, show_btns())
def new_a():
k = random.randrange(1, 3)
if k == 1:
btn_a.configure(image=a1)
elif k == 2:
btn_a.configure(image=a2)
def show_btns():
btn_b.pack(side=LEFT)
btn_c.pack(side=RIGHT)
a1 = PhotoImage(file="A1.gif")
a2 = PhotoImage(file="A2.gif")
orange = PhotoImage(file="orange_btn.gif")
green = PhotoImage(file="yellowgreen_btn.gif")
btn_a = Button(root, image=a1)
btn_a.pack()
btn_b = Button(root, image=orange)
btn_b.bind('<Button-1>', click_b)
btn_b.pack(side=LEFT)
btn_c = Button(root, image=green)
btn_c.bind('<Button-1>', click_c)
btn_c.pack(side=RIGHT)
root.mainloop()
the issues is in your after() methods.
You need to remove the brackets for the show_btns function call or else tkinter will not run this command properly. If you have a function with no arguments you leave off the () portion.
If you do have arguments then you will need to either provide those arguments in the after statement IE after(2000, some_func, arg1, arg2) or use lambda to create a one off function to do the work like after(2000, lambda: some_func(arg1, arg2)). lambda can be more complicated but this is the basic concept.
change:
after(2000, show_btns())
To:
after(2000, show_btns)
As long as your paths to your images work fine the below code should work as intended.
from tkinter import *
import random
root = Tk()
root.geometry("500x500")
def click_b(event):
btn_b.pack_forget()
btn_c.pack_forget()
new_a()
root.update()
root.after(2000, show_btns)
def click_c(event):
btn_b.pack_forget()
btn_c.pack_forget()
new_a()
root.update()
root.after(2000, show_btns)
def new_a():
k = random.randrange(1, 3)
if k == 1:
btn_a.configure(image=a1)
elif k == 2:
btn_a.configure(image=a2)
def show_btns():
btn_b.pack(side=LEFT)
btn_c.pack(side=RIGHT)
a1 = PhotoImage(file="A1.gif")
a2 = PhotoImage(file="A2.gif")
orange = PhotoImage(file="orange_btn.gif")
green = PhotoImage(file="yellowgreen_btn.gif")
btn_a = Button(root, image=a1)
btn_a.pack()
btn_b = Button(root, image=orange)
btn_b.bind('<Button-1>', click_b)
btn_b.pack(side=LEFT)
btn_c = Button(root, image=green)
btn_c.bind('<Button-1>', click_c)
btn_c.pack(side=RIGHT)
root.mainloop()
This is a simple math game which is currently in progress. The loop starts off in mainGame() which then proceeds to mainMenu(). I am trying to create 2 frames; mframe and gframe in order to .destroy() the frames later on, essentially clearing the previous interface for the next one (similar to changing pages).
error:
Label(gframe, textvariable=self.question_var).pack() #gframe stands
for game frame NameError: name 'gframe' is not defined
from tkinter import *
from random import randint
root = Tk()
mframe = Frame(root).pack()
gframe = Frame(root).pack()
frame.pack()
start = True
class mainMenu:
def __init__(self):
gframe.destroy() #gets rid of previous interface
title = Label(mframe, text = "main menu").pack() #mfame stands for menu frame
class mainGame:
def __init__(self):
if start == False:
mframe.destroy() #gets rid of previous interface
#question
self.question_var = StringVar()
Label(gframe, textvariable=self.question_var).pack() #gframe stands for game frame
#answer
self.user_answer_var = StringVar()
entry = Entry(gframe, textvariable=self.user_answer_var)
entry.pack()
submit = Button(gframe, text = "submit", command = self.check_answer).pack()
#response output
self.response_var = StringVar()
self.count = 0
self.score = 0
Label(gframe, textvariable=self.response_var).pack()
#starts loop
self.ask_question()
root.mainloop()
def ask_question(self):
if self.count == 1:
self.endGame()
num1 = randint(1, 10)
num2 = randint(1, 10)
self.question_var.set("What is "+str(num1)+" + " +str(num2)+"?")
self.true_answer = num1 + num2
#print(self.true_answer) #testing purposes
def check_answer(self):
self.count += 1
user_answer = self.user_answer_var.get()
#print(user_answer) #testing purposes
if int(user_answer) == self.true_answer:
text = "Good job"
self.score += 1
else:
text = "Oh no"
self.response_var.set(text)
#clear answer for next loop
self.user_answer_var.set("")
self.ask_question()
def endGame(self):
print("endGame")
mainMenu()
mainGame()
As said in the comments above, the pack() method returns None. What you need to do is first create the two frames and assign them to variables, then pack them later. This way, the variables still point to the frame instances and not None.
You should change;
root = Tk()
mframe = Frame(root).pack()
gframe = Frame(root).pack()
frame.pack()
start = True
to;
root = Tk()
mframe = Frame(root)
gframe = Frame(root)
mframe.pack()
gframe.pack()
start = True
The problem I am having is that the function below works fine on the first pass with regards to displaying the chosen value at the top of the OptionMenu before the 'Enter' button is clicked:
First pass
However on a second pass and any future passes to the function the chosen value is not displayed at the top of the OptionMenu (although if selected it will be used) before the 'Enter' Button is pressed:
Second etc. passes
The code is:
def load_create_list(self):
self.app = Toplevel(self.parent)
self.parent.withdraw()
self.app.title("Rgs2")
self.student = []
self.student1=[]
self.gs1=0
self.ng1=0
options = ["2", "3", "4", "5", "6", "7"]
self.results=[]
self.ngg=StringVar() #for the option menu widget the variable must be a stringVar not a normal string, int etc.
self.ng = Label(self.app, text="Number of groups")
self.ng.grid(row=2, column=0)
self.ngg.set("3")
self.ng1 = OptionMenu(self.app, self.ngg, *options)
self.ng1.grid(row=2, column=1, ipadx=10)
for i in range(0,len(self.x3)):
self.L1 = Label(self.app,text="Student")
self.L1.grid(row=i+4, column=0)
self.en = Entry(self.app)
self.en.insert(END, self.x3[i])
self.en.grid(row=i+4, column=1)
self.student.append(self.en)
self.el = int(len(self.student)+1)
for h in range(self.el,self.el+5):
self.L2 = Label(self.app,text="Student")
self.L2.grid(row=h+4, column=0)
self.em = Entry(self.app)
self.em.grid(row=h+4, column=1)
self.student.append(self.em)
button=Button(self.app,text="enter",command=lambda : self.hallo2()).grid(row=h+7,column=0)
button=Button(self.app,text="Save List",command=lambda : self.save_list2()).grid(row=h+7,column=1)
I have tried everything but can't understand what might be causing this issues. Any help would be gladly appreciated. Seems like very odd behaviour could it be something outside of the function that is causing the issue?
Full code is:
from Tkinter import *
from tkFileDialog import askopenfile
class main_menu:
def __init__(self, parent):
self.myParent = parent
self.myContainer1 = Frame(parent)
parent.title("Random Group Sorter")
self.myContainer1.pack()
self.button1 = Button(self.myContainer1, command = lambda : self.hope())
self.button1.configure(text="Create List", height = 1, width = 20, font=("Arial", 16))
self.button1.pack(side=TOP)
self.button1.focus_force()
self.button3 = Button(self.myContainer1, command = lambda : self.hope1())
self.button3.configure(text="Load List", height = 1, width = 20, font=("Arial", 16))
self.button3.pack(side=TOP)
self.button2 = Button(self.myContainer1, command = lambda : exit(), )
self.button2.configure(text="Exit",height = 1, width = 20, font=("Arial", 16))
self.button2.pack(side=TOP)
def hope(self):
self.myParent.destroy()
create_list()
def hope1(self):
self.myParent.destroy()
load_list()
class create_list():
def __init__(self):
parent = Tk()
self.parent=parent
self.student = []
self.student1 =[]
self.student2 =[]
self.fake_student = []
self.results=[]
self.ngg = StringVar()# for the option menu widget the variable must be a stringVar not a normal string, int etc.
self.ng = Label(text="Number of groups")
self.ng.grid(row=2, column=0)
self.ng = OptionMenu(parent, self.ngg, "2", "3", "4", "5","6")
self.ng.grid(row=2, column=1)
for i in range(3,21):
self.L1 = Label(text="Student")
self.L1.grid(sticky=E)
self.en = Entry(parent)
self.en.grid(row=i, column=1)
self.student.append(self.en)
button=Button(parent,text="Enter",command=lambda : self.hallo()).grid(row=23,column=0)
button=Button(parent,text="Save List",command=lambda : self.save_list()).grid(row=23,column=1)
parent.mainloop()
def hallo(self):
self.gs1 = int(len(self.student))
self.ng1 = int(self.ngg.get())# still need to use .get even though a stringvar
for entry in self.student:
self.student1.append(entry.get())
self.student1 = filter(None, self.student1)
for i in self.student1:# this is added as there are duplicate entries in the student list if saved
if i not in self.student2:
self.student2.append(i)
self.parent.destroy()
lis_an(self.student2,self.ng1)
def save_list(self):
for entry in self.student:
self.student1.append(entry.get())
self.student1 = filter(None, self.student1)
import tkFileDialog
root = Tk()
root.withdraw()
file_name = tkFileDialog.asksaveasfile(parent=root)
root.destroy()
print >>file_name, "\n"
print >>file_name, "\n".join(self.student1)
file_name.close()
class load_list:
def __init__(self):
self.x = []
self.x3 = []
self.load_clean()
self.root = Tk()
def load_clean(self):#option to load an already created file, cleans unwanted info from the list
import tkFileDialog
root = Tk()
root.withdraw()
file_name = tkFileDialog.askopenfile(parent=root)
root.destroy()
self.x = file_name.readlines()
file_name.close()
x2 =self.x[:]
for z in self.x:
if z [0:6]== "Random" or z == '\n' or z[0:5] == "Group":
x2.remove(z)
for c in range (0,len(x2)):
v = x2[c].rstrip()# this strip spaces and \n from each list item and returns the cleaned up string
self.x3.append(v)
self.load_create_list()
def load_create_list(self):
parent = Tk()
self.parent=parent
self.student = []
self.student1=[]
self.gs1=0
self.ng1=0
self.results=[]
self.ngg = StringVar()# for the option menu widget the variable must be a stringVar not a normal string, int etc.
self.ng = Label(text="Number of groups")
self.ng.grid(row=2, column=0)
self.ng = OptionMenu(parent, self.ngg, "2", "3", "4", "5", "6")
self.ng.grid(row=2, column=1)
for i in range(0,len(self.x3)):
self.L1 = Label(text="Student")
self.L1.grid(row=i+3, column=0)
self.en = Entry(parent)
self.en.insert(END, self.x3[i])
self.en.grid(row=i+3, column=1)
self.student.append(self.en)
self.el = int(len(self.student)+1)
for h in range(self.el,self.el+5):
self.L2 = Label(text="Student")
self.L2.grid(row=h+3, column=0)
self.em = Entry(parent)
self.em.grid(row=h+3, column=1)
self.student.append(self.em)
button=Button(parent,text="enter",command=lambda : self.hallo2()).grid(row=h+6,column=0)
button=Button(parent,text="Save List",command=lambda : self.save_list2()).grid(row=h+6,column=1)
parent.mainloop()
def hallo2(self):
self.student2= []
self.gs1 = int(len(self.student))
self.ng1 = int(self.ngg.get())# still need to use .get even though a stringvar
for entry in self.student:
self.student1.append(entry.get())
self.student1 = filter(None, self.student1)
for i in self.student1:# this is added as there are duplicate entries in the student list if saved
if i not in self.student2:
self.student2.append(i)
self.parent.destroy()
lis_an(self.student2,self.ng1)
def save_list2(self):
for entry in self.student:
self.student1.append(entry.get())
self.student1 = filter(None, self.student1)
import tkFileDialog
root = Tk()
root.withdraw()
file_name = tkFileDialog.asksaveasfile(parent=root)
root.destroy()
print >>file_name, "\n"
print >>file_name, "\n".join(self.student1)
file_name.close()
class lis_an:
def __init__(self,student1,ng1):
self.student1 = student1
self.ng1=ng1
self.results = []
self.randomList()
def randomList(self): # this creates a random list of students on the course
import random
studentb = self.student1[:]# this is added as otherwise the student list is overwritten
studentc = []
for i in range(len(studentb)):
element = random.choice(studentb)
studentb.remove(element)
studentc.append(element)
self.student1 = studentc
self.partition()
def partition(self): # this creates sub list of the student list containing the groups of students
increment = len(self.student1) / float(self.ng1)
last = 0
i = 1
while last < len(self.student1):
idx = int(round(increment * i))
self.results.append(self.student1[last:idx])
last = idx
i += 1
output(self.results, self.ng1)
class output:
def __init__(self, student, ng1):
self.ng1 = ng1
self.student = student
self.parent = Tk()
for item1 in range (0,len(self.student)):
test1 = "Group " + str(item1+1)+ ":"
v = Label(self.parent, text=test1, font=("Arial", 13))
test = "\n".join(self.student[item1])
w = Label(self.parent, text=test, justify = LEFT, font=("Arial", 12))
v.pack(side="top", anchor="w")
w.pack(side="top", anchor="w")
button=Button(self.parent,text="Repeat",command=lambda : self.join_list()).pack(side="top", anchor="w")
button=Button(self.parent,text="Main Menu",command=lambda : self.menu_link()).pack(side="top", anchor="w")
mainloop()
def join_list(self):#this function creates a new undivided version of student to feed back to lis_an
self.parent.destroy()
self.student = [j for i in self.student for j in i]
lis_an(self.student,self.ng1)
def menu_link(self):#destroys the parent frame and returns back to main menu
self.parent.destroy()
main()
def main():
parent = Tk()
myapp = main_menu(parent)
parent.mainloop()
main()
Very Simple solution to this problem. I was not defining self.ngg as a StringVar in the parent widget so:
self.ngg = StringVar()
Would cause the error, and
self.ngg = StringVar(self.app)
Solves the problem. Not quite sure why this would occur on the second and subsequent uses of the function but not the first.
This question already has answers here:
python tkinter how to bind key to a button
(3 answers)
Closed 4 months ago.
ok i am using this code for educational purposes and if i go 45+54 and hit enter key i dont get any answer but if use the = on the screen not on my keyboard it works. i am so stuck and stressed out because i have done so much research but not able to find my answer. all i ask for the help is that am i missing a piece of code that is stopping me to use the equals key or the enter key on the numpad. please help here this is the code:
from tkinter import *
import tkinter
# Calculator is a class derived from Frame. Frames, being someone generic,
# make a nice base class for whatever you what to create.
class Calculator(Frame):
# Create and return a packed frame.
def frame(this, side):
w = Frame(this)
w.pack(side=side, expand=YES, fill=BOTH)
return w
# Create and return a button.
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
# Enter a digit.
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)
# Change sign.
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)
# Decimal
def decimal(self):
self.need_clr = False
cont = self.display.get()
lastsp = cont.rfind(' ')
if lastsp == -1:
lastsp = 0
if cont.find('.',lastsp) == -1:
self.display.set(cont + '.')
# Push a function button.
def oper(self, op):
self.display.set(self.display.get() + ' ' + op + ' ')
self.need_clr = False
# Calculate the expressoin and set the result.
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 Enter(self):
self.display.set('Enter')
def keyPressed(self,event):
if event.keysym == 'Enter':
self.enter()
def __init__(self):
Frame.__init__(self)
self.option_add('*Font', 'Verdana 12 bold')
self.pack(expand=YES, fill=BOTH)
self.master.title('Simple Calculator')
# The StringVar() object holds the value of the Entry.
self.display = StringVar()
e = Entry(self, relief=SUNKEN, textvariable=self.display)
e.pack(side=TOP, expand=YES, fill=BOTH)
# This is a nice loop to produce the number buttons. The Lambda
# is an anonymous function.
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, '-', self.sign)
self.button(keyF, LEFT, '0', lambda ch='0': self.digit(ch))
self.button(keyF, LEFT, '.', self.decimal)
# The frame is used to hold the operator buttons.
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))
# Clear button.
clearF = self.frame(BOTTOM)
self.Enter_button = self.button(clearF, LEFT, 'Enter', self.Enter)
self.bind_all('<Key>', self.keyPressed)
# Make a new function for the - sign. Maybe for . as well. Add event
# bindings for digits to call the button functions.
# This allows the file to be used either as a module or an independent
# program.
if __name__ == '__main__':
Calculator().mainloop()
To call a the same function as a button press on a keypress you have to bind keypress to you GUI.
Example
try:
# for Python2
from Tkinter import *
except ImportError:
# for Python3
from tkinter import *
class GUI(Frame):
# Create and return a packed frame.
def frame(self, side):
w = Frame(self)
w.pack(side=side, expand=YES, fill=BOTH)
return w
# Create and return a button.
def button(self, root, side, text, command=None):
w = Button(root, text=text, command=command)
w.pack(side=side, expand=YES, fill=BOTH)
return w
def hello(self):
self.display.set('hello')
def keyPressed(self,event):
#test to see whether enetr is pressed
if event.keysym == 'Return':
self.hello()
def __init__(self):
Frame.__init__(self)
self.option_add('*Font', 'Verdana 12 bold')
self.pack(expand=YES, fill=BOTH)
self.master.title('Simple GUI')
# The StringVar() object holds the value of the Entry.
self.display = StringVar()
e = Entry(self, relief=SUNKEN, textvariable=self.display)
e.pack(side=TOP, expand=YES, fill=BOTH)
# Clear button.
clearF = self.frame(BOTTOM)
self.hello_button = self.button(clearF, LEFT, 'Hello', self.hello)
#bind keypresses
self.bind_all('<Key>', self.keyPressed)
if __name__ == '__main__':
GUI().mainloop()
for this specific example the folowing code shoulod work:
try:
# for Python2
from Tkinter import *
except ImportError:
# for Python3
from tkinter import *
# Calculator is a class derived from Frame. Frames, being someone generic,
# make a nice base class for whatever you what to create.
# Calculator is a class derived from Frame. Frames, being someone generic,
# make a nice base class for whatever you what to create.
class Calculator(Frame):
# Create and return a packed frame.
def frame(this, side):
w = Frame(this)
w.pack(side=side, expand=YES, fill=BOTH)
return w
def keyPressed(self,event):
#test to see whether enetr is pressed
if event.keysym == 'Return':
self.calc()
# Create and return a button.
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
# Enter a digit.
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)
# Change sign.
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)
# Decimal
def decimal(self):
self.need_clr = False
cont = self.display.get()
lastsp = cont.rfind(' ')
if lastsp == -1:
lastsp = 0
if cont.find('.',lastsp) == -1:
self.display.set(cont + '.')
# Push a function button.
def oper(self, op):
self.display.set(self.display.get() + ' ' + op + ' ')
self.need_clr = False
# Calculate the expressoin and set the result.
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 __init__(self):
Frame.__init__(self)
self.option_add('*Font', 'Verdana 12 bold')
self.pack(expand=YES, fill=BOTH)
self.master.title('Simple Calculator')
# The StringVar() object holds the value of the Entry.
self.display = StringVar()
e = Entry(self, relief=SUNKEN, textvariable=self.display)
e.pack(side=TOP, expand=YES, fill=BOTH)
# This is a nice loop to produce the number buttons. The Lambda
# is an anonymous function.
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, '-', self.sign)
self.button(keyF, LEFT, '0', lambda ch='0': self.digit(ch))
self.button(keyF, LEFT, '.', self.decimal)
# The frame is used to hold the operator buttons.
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))
# Clear button.
clearF = self.frame(BOTTOM)
self.button(clearF, LEFT, 'Clr', lambda w=self.display: w.set(''))
self.bind_all('<Key>', self.keyPressed)
# Make a new function for the - sign. Maybe for . as well. Add event
# bindings for digits to call the button functions.
# This allows the file to be used either as a module or an independent
# program.
if __name__ == '__main__':
Calculator().mainloop()