[Python 2.7] Hello. I'm working on a simple Tkinter calculator program, but can't seem to get the label to display any text after I push one of the buttons. Here is the code I'm using, some of the button functions are unfinished until I can get the label itself working:
from Tkinter import *
import ttk
"""Calculator"""
#Variables
Entered = ""
#Button Functions
def Natural_Log():
pass
def Exp():
Entered = "^"
def Sin():
pass
def Cos():
pass
def Tan():
pass
def LeftParentheses():
Entered = Entered + "("
def RightParentheses():
Entered = Entered + ")"
def Log():
pass
def XSquared():
Entered = Entered + "**2"
def InvX():
Entered = Entered + "**-1"
def Seven():
Entered = Entered + "7"
def Eight():
Entered = Entered + "8"
def Nine():
Entered = Entered + "9"
def DEL():
Entered = Entered[:1]
def AC():
Entered = ""
def Four():
Entered = Entered + "4"
def Five():
Entered = Entered + "5"
def Six():
Entered = Entered + "6"
def Mult():
Entered = Entered + "*"
def Div():
Entered = Entered + "/"
def One():
Entered = Entered + "1"
def Two():
Entered = Entered + "2"
def Three():
Entered = Entered + "3"
def Plus():
Entered = Entered + "+"
def Minus():
Entered = Entered + "-"
def Zero():
Entered = Entered + "0"
def Decimal():
Entered = Entered + "."
def Ex():
pass
def neg():
pass
def EXE():
pass
#Main Window Setup:
#Root setup
root = Tk()
root.title("Generic Calculator")
#Parent frame setup
mainframe = ttk.Frame(root,padding="8")
mainframe.grid(column=0,row=0,sticky=(N,S,E,W))
mainframe.columnconfigure(0,weight=1)
mainframe.rowconfigure(0,weight=1)
#Button setup
ttk.Button(mainframe,text="ln",command=Natural_Log).grid(column=1,row=2,sticky=W)
ttk.Button(mainframe,text="^",command=Exp).grid(column=2,row=2,sticky=W)
ttk.Button(mainframe,text="sin",command=Sin).grid(column=3,row=2,sticky=W)
ttk.Button(mainframe,text="cos",command=Cos).grid(column=4,row=2,sticky=W)
ttk.Button(mainframe,text="tan",command=Tan).grid(column=5,row=2,sticky=W)
ttk.Button(mainframe,text="(",command=LeftParentheses).grid(column=1,row=3,sticky=W)
ttk.Button(mainframe,text=")",command=RightParentheses).grid(column=2,row=3,sticky=W)
ttk.Button(mainframe,text="log",command=Log).grid(column=3,row=3,sticky=W)
ttk.Button(mainframe,text="x^2",command=XSquared).grid(column=4,row=3,sticky=W)
ttk.Button(mainframe,text="x^-1",command=InvX).grid(column=5,row=3,sticky=W)
ttk.Button(mainframe,text="7",command=Seven).grid(column=1,row=4,sticky=W)
ttk.Button(mainframe,text="8",command=Eight).grid(column=2,row=4,sticky=W)
ttk.Button(mainframe,text="9",command=Nine).grid(column=3,row=4,sticky=W)
ttk.Button(mainframe,text="DEL",command=DEL).grid(column=4,row=4,sticky=W)
ttk.Button(mainframe,text="AC",command=AC).grid(column=5,row=4,sticky=W)
ttk.Button(mainframe,text="4",command=Four).grid(column=1,row=5,sticky=W)
ttk.Button(mainframe,text="5",command=Five).grid(column=2,row=5,sticky=W)
ttk.Button(mainframe,text="6",command=Six).grid(column=3,row=5,sticky=W)
ttk.Button(mainframe,text="*",command=Mult).grid(column=4,row=5,sticky=W)
ttk.Button(mainframe,text="/",command=Div).grid(column=5,row=5,sticky=W)
ttk.Button(mainframe,text="1",command=One).grid(column=1,row=6,sticky=W)
ttk.Button(mainframe,text="2",command=Two).grid(column=2,row=6,sticky=W)
ttk.Button(mainframe,text="3",command=Three).grid(column=3,row=6,sticky=W)
ttk.Button(mainframe,text="+",command=Plus).grid(column=4,row=6,sticky=W)
ttk.Button(mainframe,text="-",command=Minus).grid(column=5,row=6,sticky=W)
ttk.Button(mainframe,text="0",command=Zero).grid(column=1,row=7,sticky=W)
ttk.Button(mainframe,text=".",command=Decimal).grid(column=2,row=7,sticky=W)
ttk.Button(mainframe,text="EXP",command=Ex).grid(column=3,row=7,sticky=W)
ttk.Button(mainframe,text="(-)",command=neg).grid(column=4,row=7,sticky=W)
ttk.Button(mainframe,text="EXE",command=EXE).grid(column=5,row=7,sticky=W)
#Label Setup:
EnteredSetup = StringVar()
ttk.Label(mainframe,textvariable=EnteredSetup).grid(column=1,row=1,columnspan=5)
EnteredSetup.set(Entered)
root.mainloop()
I believe there is a misunderstanding on how StringVar works. The line
EnteredSetup.set(Entered)
does not create some form of link between EnteredSetup and Entered, modifying Entered does not issue updates in EnteredSetup. Your code can be improved a lot too, and you should post something that is only long enough to describe the problem. Said that, consider this reduced version already fixed (note that it could be much smaller):
from Tkinter import Tk, StringVar
import ttk
class Calculator:
def __init__(self, state):
self.state = state
def ac(self):
self.state.set('')
def state_num(self, num):
self.state.set('%s%d' % (self.state.get(), num))
#Main Window Setup:
#Root setup
root = Tk()
root.title("Generic Calculator")
EnteredSetup = StringVar('')
calc = Calculator(EnteredSetup)
#Parent frame setup
mainframe = ttk.Frame(root, padding="8")
mainframe.grid(column=0, row=0)
mainframe.columnconfigure(0, weight=1)
mainframe.rowconfigure(0, weight=1)
#Button setup
ttk.Button(mainframe, text="AC", command=calc.ac).grid(
column=5, row=4)
ttk.Button(mainframe, text="1", command=lambda: calc.state_num(1)).grid(
column=1, row=6)
ttk.Button(mainframe, text="0", command=lambda: calc.state_num(0)).grid(
column=1, row=7)
#Label Setup:
ttk.Label(mainframe, textvariable=EnteredSetup).grid(
column=1,row=1,columnspan=5)
root.mainloop()
I hope this guides you in the right direction for further adjusting your calculator.
Related
I've been coding a program that would let you practice multiplication, on the program, I've made it so the user can select what numbers they want to practice with checkboxes. I've managed to get it working but I was wondering if there is a more iterative way of doing it since i want to go from 1 to 12. I've seen ways of making checkboxes from a list but I haven't been able to get it to work.
from msilib.schema import CheckBox
from tkinter import *
import random
from tkinter import messagebox
class Timestable:
def __init__(self, parent):
self.f1 = Frame(parent)
self.f1.grid()
self.f2 = Frame(parent)
self.f2.grid()
self.f2.grid_forget()
self.f3 = Frame(parent)
self.f3.grid()
self.f3.grid_forget()
#frame 1 ========================================================
Label(self.f1,text="Multiplication Practice").grid()
Label(self.f1,text="Name:").grid()
self.name = Entry (self.f1)
self.name.grid()
Label(self.f1,text="Age").grid()
self.age = Entry (self.f1)
self.age.grid()
self.user = []
self.incorrect=[]
self.checked1 = IntVar()
self.checked2 = IntVar()
self.c1 = Checkbutton(self.f1, text='1',variable=self.checked1,onvalue=1,offvalue=0,command=self.save)
self.c1.grid()
self.c2 = Checkbutton(self.f1, text='2', variable=self.checked2,onvalue=1,offvalue=0,command=self.save)
self.c2.grid()
self.w = Spinbox(self.f1, from_=1, to=5)
self.w.grid()
Button(self.f1,text="Start", command=self.start).grid()
#frame 2 ========================================================
Label(self.f2,text="Frame 2 ").grid()
self.x=0
self.correct=0
sub = lambda: Timestable.Submit(self)
Button(self.f2,text="submit", command=sub).grid()
self.entryWidget = Entry (self.f2)
self.entryWidget.grid()
#frame 3 ========================================================
Label(self.f3,text="Frame 3 ").grid()
# ===============================================================
def save(self):
if self.checked1.get() == 1:
self.user.append(1)
if self.checked2.get() == 1:
self.user.append(2)
#self.user.append(self.checked1.get())
def clear_text(self):
self.entryWidget.delete(0, 'end')
def Questions(self):
number1 = random.choice(self.user)
number2 = random.randrange(1,12)
self.answer = number1 * number2
self.prompt = (str(number1) + " X " + str(number2))
quest = Label(self.f2, text=self.prompt, width=len(self.prompt))
quest.grid()
return self.answer
def start(self):
self.f1.grid_forget()
self.f2.grid()
self.Questions()
def results(self):
self.f2.grid_forget()
self.f3.grid()
def Submit(self):
if self.entryWidget.get() == "":
messagebox.showerror("Error", "Please enter a number.")
elif self.entryWidget.get() == str:
messagebox.showerror("Error", "Please enter a number, not letters.")
else:
if self.answer != int(self.entryWidget.get().strip()):
messagebox.showinfo("Answer", "INCORRECT! Answer: " + str(self.answer))
self.incorrect.append(self.prompt)
else:
messagebox.showinfo("Answer", "CORRECT!")
self.correct = self.correct +1
self.x=self.x+1
if self.x < int(self.w.get()):
self.Questions()
self.clear_text()
else:
self.results()
self.percent = round(self.correct/self.x*100)
Label(self.f3,text="Congrats, you got "+ str(self.percent) +"% of the questions correct" ).grid()
Label(self.f3,text = self.incorrect).grid()
root = Tk()
root.geometry("200x300")
Timestable(root)
root.mainloop()
Instead of creating the checkboxes one by one, you can use a for loop to create them:
class Timestable:
def __init__(self, parent):
...
self.user = []
self.incorrect = []
# -- create those checkboxes
# list to store the tkinter variables for those checkboxes
self.checked = []
# suggest to create those checkboxes inside a frame
# and put 3 checkboxes in a row
frame = Frame(self.f1)
frame.grid()
for i in range(12):
self.checked.append(IntVar()) # store the tkinter variable for the checkbox
Checkbutton(frame, text=i+1, variable=self.checked[-1], onvalue=i+1, offvalue=0, anchor='w').grid(row=i//3, column=i%3, sticky='ew')
...
Note that I don't require the save(). You can build the self.user inside start():
def start(self):
# get the user selected numbers
self.user = [v.get() for v in self.checked if v.get()]
# you can check the user list
#print(self.user)
if self.user:
# only start the game when there are numbers selected
self.f1.grid_forget()
self.f2.grid()
self.Questions()
so, i opened a question about it yesterday but it got closed saying its a dupe, let me explain my question more specificly then, hoping im not passinng any law here..
im trying to set a default message that will be set as gray and low opacity in the entry widget on tkinter, that after being focused in will dispear.
i managed to do that, but i got into a problem.
the default text is "enter username" for example, but if someone tries to do this user name it says that the username entry is empty which isnt what i wanna do..
i hope you understood my question.
edit: my question is how to do a placeholder text, while allowing the user to input the same text as the placeholder.
thanks in advance, this is my code:
from tkinter import *
from tkinter import messagebox
main = Tk()
main.title("ani gever")
checkbox_var = IntVar()
def delete_user_default(event):
if User_entry.get()!="enter username":
pass
else:
User_entry.delete(0, END)
def delete_password_default(event):
if password_entry.get() !="insert password":
pass
else:
password_entry.delete(0, END)
password_entry.config(show="*")
def return_user_default(event):
if User_entry.get()=="":
User_entry.insert(0, "enter username")
emptyuser=1
else:
pass
def return_password_default(event):
if password_entry.get()=="":
password_entry.insert(0,"insert password")
password_entry.config(show="")
else:
pass
def details(event):
if ((User_entry.get() == "enter username") or (password_entry.get() == "insert password")):
errorLabel.config(text="Username or password is empty!",fg="red")
elif ((" " in User_entry.get()) or " " in password_entry.get()):
errorLabel.config(text="dont use spaces in your password or username!", fg="red")
else:
print ("username:" + User_entry.get() + "\npassword:" + password_entry.get())
errorLabel.config(text="")
#============== define texts=======================
User_label= Label(main,text="Username:")
password_label= Label(main,text="Password:")
User_entry = Entry(main)
password_entry= Entry(main,show="*")
enterButton= Button(main,text="Log in")
errorLabel= Label(main,text="")
#=============default text on entry's=============
password_entry.config(show="")
User_entry.insert(0,"enter username")
password_entry.insert(0,"insert password")
User_entry.bind("<FocusIn>",delete_user_default)
password_entry.bind("<FocusIn>",delete_password_default)
User_entry.bind("<FocusOut>",return_user_default)
password_entry.bind("<FocusOut>",return_password_default)
#=============return user details ===========
User_entry.bind("<Return>",details)
password_entry.bind("<Return>",details)
enterButton.bind("<Button-1>",details)
#=============place everything on screen===========
User_label.grid(row=0,sticky= W)
User_entry.grid(row=0,column=1,sticky= W)
password_label.grid(row=1,sticky= W)
password_entry.grid(row=1,column=1,sticky= W)
enterButton.grid(row=2,sticky=W)
errorLabel.grid(row=3,columnspan=10,sticky= W)
main.mainloop()
Using this answer an is_empty function can be created. It prints True if validated entry is 'empty' and False if not.
import tkinter as tk
class EntryWithPlaceholder(tk.Entry):
def __init__(self, master=None, placeholder="PLACEHOLDER", color='grey'):
super().__init__(master)
self.placeholder = placeholder
self.placeholder_color = color
self.default_fg_color = self['fg']
self.bind("<FocusIn>", self.foc_in)
self.bind("<FocusOut>", self.foc_out)
self.put_placeholder()
def put_placeholder(self):
self.insert(0, self.placeholder)
self['fg'] = self.placeholder_color
def foc_in(self, *args):
if self['fg'] == self.placeholder_color:
self.delete('0', 'end')
self['fg'] = self.default_fg_color
def foc_out(self, *args):
if not self.get():
self.put_placeholder()
def is_empty(widget, empty_color):
if widget.get():
if widget['fg'] == empty_color:
print (True)
else:
print (False)
else:
print (True)
if __name__ == "__main__":
root = tk.Tk()
username = EntryWithPlaceholder(root, "username")
password = EntryWithPlaceholder(root, "password", 'blue')
username.pack()
password.pack()
tk.Button(root, text="Validate",
command=lambda wid=username, clr=username.placeholder_color:
is_empty(wid, clr)).pack()
root.mainloop()
I am going to write program that calculate just a number with (123) and show sum of them to me. But i want write a code that when (sum) button pressed do this:{if the field doesn't have any integer type of number call errorMsg function and else calculate numbers} but I don't know how can I do this. Please help!
from tkinter import *
frame = Tk()
def textBoxes():
global e1
e1 = Entry(frame,justify=LEFT )
def labels():
var1 = StringVar()
var1.set("Enter first number: ")
label1 = Label(frame, textvariable = var1)
var3=StringVar()
def errorMsg():
msg = messagebox.showinfo("Please Enter Some Number!")
def calculator():
#def __init__(self,String_value1,String_value2,sum_result)
String_value1 = e1.get()
Int_value1 = int(String_value1)
if not(String_value1.get()):
errorMsg()
else:
sum_result = Int_value1 + 123
def buttons():
B1 = Button(frame, text="Sum", command=calculator)
buttons()
labels()
textBoxes()
frame.mainloop()
In your calculator method, instead of checking if it's empty or not, try to operate on your value and catch the exceptions if it fails. It is called Easier to ask for forgiveness than permission.
result = StringVar()
def calculator():
try:
user_input = int(e1.get())
result.set(str(user_input+123)) #or however you like to show this
except ValueError:
errorMsg()
Little snippet, using your code:
import tkinter as tk
from tkinter import messagebox
frame = tk.Tk()
var1 = tk.StringVar()
var3 = tk.StringVar()
ent1 = tk.Entry(frame,justify="left")
var1.set("Enter first number: ")
var3.set("Result")
def textBoxes():
ent1.pack()
def labels():
tk.Label(frame, textvariable=var3).pack()
tk.Label(frame, textvariable=var1).pack()
def errorMsg():
messagebox.showinfo("Error", "Please enter a valid number!")
def calculator():
try:
user_input = int(ent1.get())
var3.set("Result = "+str(user_input+123))
except ValueError:
var3.set("Please enter a valid number!")
errorMsg()
def buttons():
tk.Button(frame, text="Sum", command=calculator).pack()
labels()
textBoxes()
buttons()
frame.mainloop()
Forgive me if this is a badly mangled way of doing things, but I'm new to development in general.
I am trying to create a window with a number of buttons using tkinter, each button having the name of a player on it using a class called from main().
I then want to be able to use the name on the button that is pressed later in the app, so I want to pass that back to main(). So, if I click on the Annie button, I want to open up a new window later called 'Options for Annie' and I'm assuming that the value 'Annie' needs to be passed back to the main function.
My main code:
<imports appear here>
def main():
players = ['Annie','Benny','Carrie','Donny']
winHome = playerWindow(root,players)
print("In main() : " + winHome.selected)
root.mainloop()
if __name__ == "__main__":
main()
My class code:
<imports appear here>
root=Tk()
class playerWindow():
def selectPlayer(self,selname):
self.selected = selname
print("In class: " + self.selected)
def __init__(self, master, players=[]):
colours = ['red','green','orange','white','yellow','blue']
self.selected = ""
r = 0
for p in players:
randcol = random.randint(0,len(colours))-1
if colours[randcol] in ('blue','green'):
fgcol='white'
else:
fgcol='black'
playername = delplayer = p
playername = Button(root, text=playername, bg=colours[randcol], fg=fgcol, width=15, command=lambda name = playername:self.selectPlayer(name)).grid(row=r,column=0)
s = ttk.Separator(root, orient=VERTICAL)
delplayer = Button(root, text='Del', bg='grey', fg='red', width=5, command=lambda name = delplayer: print("Delete Player %s" % name)).grid(row=r,column=1)
r = r + 1
Button(root, text="New Player", fg="black", command=lambda: print("New Player Functionality"), width=15).grid(row = len(players)+3,column=0)
Button(root, text="QUIT", fg="red", command=root.destroy, width=15).grid(row = len(players)+3,column=1)
What is happening is that the window gets created, the next line in main() is run (my added print statement) which is empty, obviously as main is continuing. When I press the button, the sleectPlayer function is called and works.
Somehow I need to get the value back to main() to go on to the next task using that value, however I don't seem to be able to frame the question correctly to get the answers I need.
Any help would be greatly appreciated.
I am using Python 3.5.1
You are already accessing it. I personally don't like returning to the main function, instead I suggest creating a top-level class to link back to. This should help make things flow better.
import tkinter as tk
from tkinter import ttk
import random
class PlayerWindow():
def __init__(self, master, parent, players=[]):
self._parent = parent
colours = ['red','green','orange','white','yellow','blue']
self.selected = ""
r = 0
for p in players:
randcol = random.randint(0,len(colours))-1
if colours[randcol] in ('blue','green'):
fgcol='white'
else:
fgcol='black'
playername = delplayer = p
playername = tk.Button(master, text=playername, bg=colours[randcol], \
fg=fgcol, width=15, command=lambda name = \
playername:self.selectPlayer(name)).grid(row=r,column=0)
s = ttk.Separator(master, orient=tk.VERTICAL)
delplayer = tk.Button(master, text='Del', bg='grey', fg='red', \
width=5, command=lambda name = delplayer: \
print("Delete Player %s" % name)).grid(row=r,column=1)
r = r + 1
tk.Button(master, text="New Player", fg="black", command=lambda: \
print("New Player Functionality"), width=15).\
grid(row = len(players)+3,column=0)
tk.Button(master, text="QUIT", fg="red", command=self._parent.close,
width=15).grid(row = len(players)+3,column=1)
def selectPlayer(self, selname):
self.selected = selname
print("In class: " + self.selected)
self._parent.hello() # call hello function of top-level, links back
class MyApplication(object):
def __init__(self, master):
self._master = master
players = ['Annie','Benny','Carrie','Donny']
self._player_window = PlayerWindow(master, self, players)
print("In main() : " + self._player_window.selected)
def hello(self):
name = self._player_window.selected
print("Hello, %s" % name)
def close(self):
# any other clean-up
self._master.destroy()
def main():
root = tk.Tk()
app = MyApplication(root)
root.mainloop()
if __name__ == "__main__":
main()
I am learning python and am having trouble getting this program to work correctly.
from Tkinter import*
import time
import tkMessageBox
import random
def Questions():
number1 = random.randrange(1,25,1)
number2 = random.randrange(1,50,2)
answer = number1 + number2
prompt = ("Add " + str(number1) + " and " + str(number2))
label1 = Label(root, text=prompt, width=len(prompt), bg='yellow')
label1.pack()
return answer
def start():
global count_flag
Questions()
count_flag = True
count = 0.0
while True:
if count_flag == False:
break
# put the count value into the label
label['text'] = str(count)
# wait for 0.1 seconds
time.sleep(0.1)
# needed with time.sleep()
root.update()
# increase count
count += 0.1
def Submit(answer, entryWidget):
""" Display the Entry text value. """
global count_flag
count_flag = False
print answer
if entryWidget.get().strip() == "":
tkMessageBox.showerror("Tkinter Entry Widget", "Please enter a number.")
if int(answer) != entryWidget.get().strip():
tkMessageBox.showinfo("Answer", "INCORRECT!")
else:
tkMessageBox.showinfo("Answer", "CORRECT!")
# create a Tkinter window
root = Tk()
root.title("Math Quiz")
root["padx"] = 40
root["pady"] = 20
# Create a text frame to hold the text Label and the Entry widget
textFrame = Frame(root)
#Create a Label in textFrame
entryLabel = Label(textFrame)
entryLabel["text"] = "Answer:"
entryLabel.pack(side=LEFT)
# Create an Entry Widget in textFrame
entryWidget = Entry(textFrame)
entryWidget["width"] = 50
entryWidget.pack(side=LEFT)
textFrame.pack()
#directions
directions = ('Click start to begin. You will be asked a series of questions like the one below.')
instructions = Label(root, text=directions, width=len(directions), bg='orange')
instructions.pack()
# this will be a global flag
count_flag = True
answer = Questions()
Sub = lambda: Submit(answer, entryWidget)
# create needed widgets
label = Label(root, text='0.0')
btn_submit = Button(root, text="Submit", command = Sub)
btn_start = Button(root, text="Start", command = start)
btn_submit.pack()
btn_start.pack()
label.pack()
# start the event loop
root.mainloop()
It just says "INCORRECT!" every time I push submit regardless of what I enter into the text box. Any suggestions would be appreciated. Thanks, Scott
Left side is an integer, right side is a string, so it's always False:
int(answer) != entryWidget.get().strip()
You can try:
int(answer) != int(entryWidget.get().strip())