Tkinter calculator, can only do 1 operation - python

import tkinter
import tkinter.messagebox
import sys
top=tkinter.Tk()
from tkinter import*
def clear():
e1.delete(0,END)
return
def seven():
v.set(v.get()+str("7"))
v.get()
def eight():
v.set(v.get()+str("8"))
v.get()
def nine():
v.set(v.get()+str("9"))
v.get()
def four():
v.set(v.get()+str("4"))
v.get()
def five():
v.set(v.get()+str("5"))
v.get()
def six():
v.set(v.get()+str("6"))
v.get()
def one():
v.set(v.get()+str("1"))
v.get()
def two():
v.set(v.get()+str("2"))
v.get()
def three():
v.set(v.get()+str("3"))
v.get()
def zero():
v.set(v.get()+str("0"))
v.get()
def add():
global op1
op1=v.get()
e1.delete(0,END)
def equals():
v.set(int(op1)+int(v.get()))
v.get()
top.title("D & R Calculator")
top.geometry("290x240")
from tkinter import*
frame=Frame(top)
frame.grid(column=0,row=0)
framenum=Frame(top,height=265)
framenum.grid()
v=StringVar()
from tkinter import*
e1=Entry(frame,width=30,textvariable=v)
e1.grid(row=0,column=0,sticky=W+E)
b7=tkinter.Button(framenum,text="7",height=3,width=9,command=seven)
b7.grid(row=0,column=1)
b8=tkinter.Button(framenum,text="8",height=3,width=9,command=eight)
b8.grid(row=0,column=2)
b9=tkinter.Button(framenum,text="9",height=3,width=9,command=nine)
b9.grid(row=0,column=3)
b4=tkinter.Button(framenum,text="4",height=3,width=9,command=four)
b4.grid(row=1,column=1)
b5=tkinter.Button(framenum,text="5",height=3,width=9,command=five)
b5.grid(row=1,column=2)
b6=tkinter.Button(framenum,text="6",height=3,width=9,command=six)
b6.grid(row=1,column=3)
b1=tkinter.Button(framenum,text="1",height=3,width=9,command=one)
b1.grid(row=2,column=1)
b2=tkinter.Button(framenum,text="2",height=3,width=9,command=two)
b2.grid(row=2,column=2)
b3=tkinter.Button(framenum,text="3",height=3,width=9,command=three)
b3.grid(row=2,column=3)
b0=tkinter.Button(framenum,text="0",height=3,width=9,command=zero)
b0.grid(row=3,column=2)
f1=tkinter.Button(framenum,text="+",height=3,width=9,command=add)
f1.grid(row=2,column=4)
f2=tkinter.Button(framenum,text="-",height=3,width=9)
f2.grid(row=1,column=4)
f3=tkinter.Button(framenum,text="X",height=3,width=9)
f3.grid(row=0,column=4)
f4=tkinter.Button(framenum,text="/",height=3,width=9)
f4.grid(row=3,column=4)
eq=tkinter.Button(framenum,text="=",height=3,width=9,command=equals)
eq.grid(row=3,column=3)
c=tkinter.Button(framenum,text="CE",height=3,width=9,command=clear)
c.grid(row=3,column=1)
top.mainloop
I challenged myself to make a tkinter calculator WITHOUT using a tutorial. I've finally made it work but there is one problem. It can only do one function. Be it addition,multiplication,division or taking away it can only do one operation.All I want to know is how would I make the calculator remember which button was pressed/ which command so it could differentiate between different functions. Basically, I need help or guidance in making the calculator do all operations, instead of just having it do one operations and having to manually go and edit it to make it do another operation. Help or even just a push in the right direction would be great, I am very new to Python.

Alright so there are a few of things wrong with you code:
You are missing the parentheses after top.mainloop()
You have the line from tkinter import * heaps of times, this
doesn't matter really, but you only need it once at the top, and can
do away with all the other imports at the top as well.
You need to globalise op1 in the equals function.
You haven't written functions for the divide, subtract and multiply
buttons, so how could they work? When I try 9 - 6 and hit equals I
get a NameError op1 is not defined it tries to equal something but
can't as the subtract button doesn't do anything yet.
This means that you can only start with the adding button, so I try 5 + 4 and hit equals, which
works sweet and gives me 9, but if you the try to minus 5 from the result it will put a 5 in the text box and add five again when you hit equals.
When I try to start with 9 - 6 as mentioned earlier, it won't work. To get around this issue with how op1 relates to adding, and in the equals function op1 is used in a way it will only work for the adding function you need a try/except loop:
def equals():
try:
v.set(int(op1)+int(v.get()))
v.get()
del op1
except NameError:
try:
# Whatever needs to be written for subtraction to work
# (using op2 as variable?) something like this:
v.set(int(op2)-int(v.get()))
v.get()
del op2
except NameError:
try:
# etc. etc. until you have done all four equals methods...
where op2 is set in the subtracting function etc.
This should give you some help to be able to continue, if you want I can fix program for you, but only if you don't want to do it yourself?

Related

Tkinter automatically update Label after Entry in Python

I made an tkinter window for some kind of calculation from the data entered. I simplified my code below to illustrate my question. Currently, the result will show up once I click search. However, I want the result to show up automatically once text are entered in the entry box without the "search" button. I tried "after" using window.after(100, self.searchbarcode) but it did not work for me. Appreciate your inputs. Thank you!
from tkinter import *
import pandas as pd
import tkinter as tk
import os.path
import numpy as np
class searchloc:
def __init__(self):
window=tk.Tk()
window.geometry("800x300")
window.title("Search Location")
Label(window, text="Scan",font="Helvetica 24").grid(row=1,column=1,sticky=W)
self.barcode=StringVar()
self.outcomes=StringVar()
self.text1=tk.Entry(window,textvariable=self.barcode,font="Helvetica 36")
self.text1.grid(row=1,column=2,padx=(0,5))
Label(window,textvariable=self.outcomes,font="Helvetica 68 bold").grid(row=7,column=2,sticky=E)
wsheet1 = gsheet.worksheet("Sheet2")
mydata1 = wsheet1.get_values()
mydata2=mydata1[1:]
cool=mydata1[0]
look = pd.DataFrame(mydata2, dtype=str)
#window.after(1, self.searchbarcode())
#self.text1.bind('<Enter>', self.searchbarcode())
Button(window,text='search',command=self.searchbarcode,font="Helvetica 38").grid(row=5,column=2,padx=(100,5),pady=5,sticky=W)
#Button(window,text='clear',command=self.clear_text,font="Helvetica 38").grid(row=5,column=2,padx=(100,5),pady=5,sticky=E)
window.mainloop()
#def clear_text(self):
def searchbarcode(self):
bar = self.barcode.get()
outtt=bar[1:5]
self.outcomes.set(outtt)
self.text1.delete(0, 'end')
searchloc()
If you want to happen when you press the return key, you almost had it right. The function has to accept an event parameter even if you don't use it, and you need to make sure you pass the function itself, not the result of calling the function (ie: self.searchbarcode instead of self.searchbarcode()).
Also, the event is <Return>. <Enter> is for when the mouse enters the widget.
def __init__(self):
...
self.text1.bind('<Return>', self.searchbarcode)
...
def searchbarcode(self, event):
...
If you want to call searchbarcode both with or without the event parameter, give it a default value of None:
def searchbarcode(self, event=None):
...

tkinter: how to accept multiple inputs from the user one by one in a pop-up?

So I have a root widget, I want to create a pop-up that accepts the number of teachers teaching each of say 10 subjects. (something like 3 math teachers, 2 English teachers etc)
And I want to use that number that the user has entered in a for loop. Any suggestions on another way I could stucture accepting multiple inputs one-by-one would be greatly appreciated!
from tkinter import *
from random import *
def start():
popup = Toplevel() #this doesnt throw an error when kept in main part of program, why?
popup.geometry('400x300')
for x in ['chem','math','eng']:
accept(x)
def accept(sub):
global entry, label2
label2=Label(popup,text="Enter the number of {} teachers".format(sub))
label2.pack()
entry=Entry(popup) #entry box
entry.pack()
nextb=Button(popup,text='NEXT',command=lambda:nextentry(sub))
nextb.pack()
def nextentry(subject):
global entry
n=int(entry.get())
l=[i+1 for i in range(n)] #i basically want the int of the input, i'm getting an error helppp??
for k in range(n):
allsec[k].append(subject+str(choice(l)))
entry.delete(first=0,last='end')
#----------MAIN----------#
allsec=[[],[],[]]
root=Tk()
root.geometry("600x400")
l1=Label(root,text='USER INPUT')
button=Button(root,text='Start',command=start)
[i.pack() for i in [l1,button]]
root.mainloop()
print(allsec)

Python - How to 'set' an argument?

I'm working hard to solve this problem, can someone help me ?
There is what I mean by 'set' an argument:
from tkinter import *
window = Tk()
I=1
def add():
global I
menu1.add_command(label=I, command=lambda:Text(I))
I=I+1
def Text(I):
print(I)
menubar = Menu(window)
menu1 = Menu(menubar, tearoff=0)
menu1.add_command(label="Add", command=add)
menu1.add_separator()
menu1.add_command(label="Quit", command=window.quit)
menubar.add_cascade(label="Files", menu=menu1)
window.config(menu=menubar)
window.mainloop()
I want when we click on add and after on '1' it print '1', and when we add '2' and click on it, it print '2' but it always print the value of I, how can I set the argument by
menu1.add_command(label=I, command=lambda:Text(1))
for exemple ?
I don't know if I'm clear but I don't know how explain it !
Change your Text function to be a closure:
def Text(I):
def inner():
print(I)
return inner
Then change your add function to be this:
def add():
global I
text = Text(I)
menu1.add_command(label=I, command=text)
I=I+1
This will save the I in the text variable. The text variable is actually a function, inner, that will print I when called.
Or you could make your closure inline if you wanted to use the Text function somewhere else:
import functools
...
menu1.add_command(label=I, command=functools.partial(Text, i))
I think your problem is the lambda:Text(I). In this case, you have created a closure, but the closure knows I to be a global and is evaluating it at a later date.
You probably want to immediately evaluate Text(I) and use that as your result:
texti = Text(I) # Immediate evaluation
menu1.add_command(label=I, command=lambda:texti) # Return prior value of "I"

Simple GUI buttons and inputs

I am currently in an intro cs class and have a question about simple GUI and more specifically how to take a number (ex 6,7,8) input and when a button is pressed take the input number and determine if it is even or odd so far below is what I have and I get the error message that states: "button_handler() takes exactly 1 arguments (0 given)" Can someone explain to me what I am doing wrong?
import simplegui
global text_input
frame = simplegui.create_frame('Testing', 250, 250)
label = frame.add_label('Divisable by 6?')
def input_handler(text_input):
print "You entered,", text_input
def button_handler(num):
if float(num) / 6 == 0:
print "divisable by six"
else:
print "Not divisable by 6"
button1 = frame.add_button('divisable by 6?', button_handler)
inp = frame.add_input('Please insert number', input_handler, 50)
frame.start()
(BTW the formatting is weird when copied and pasted from code skulptor)
I am familiar with with tkinter and have not used simplegui, but from the error message, I can guess the problem.
button_handler is a callback that is called without any arguments when the button is clicked. But you define it with a parameter number. You have to re-write button_handler to get the number from the input some other way. I know how to do that with tkinter, but not for simplegui. Perhapsinput_handlershould write a global thatbutton_handler` can access.
In this line here:
button1 = frame.add_button('divisable by 6?', button_handler)
you are not feeding anything to button_handler. In other words, it has no arguments. But elsewhere in your code you mandate that button_handler has exactly one argument. So, you need to update your reference to button_handler in the line above to account for that fact.
(That's the fundamental bit, anyway: I don't want to comment on the rest of your code, since you say it is under construction.)
From the CodeSculptor documentation for frame.add_button():
The handler should be defined with no parameters
You can grab the content of an input field with get_text(). Here is a simple example that prints the content of an input field when a button is pressed:
import simplegui
def input_handler(text_input):
pass
def button_handler():
print inp.get_text()
frame = simplegui.create_frame("Demonstration of input and button", 300, 300)
inp = frame.add_input("Input:", input_handler, 100)
frame.add_button("Print", button_handler, 100)
frame.start()

tkinter button press to function call

hey guys first post and what not so hi. anyway trying to make a scientific calculator with tkinter and im not very good with it(and python its my second proper assignment). anyway most of the code will probably be wrong but im just trying to take it one step at a time in particular im concerned about the function add. im calling it via the button however i want to pass the do function a +. this in turn creating an array i can calculate from. it keeps erroring and i dont know how to fix it. its really annoying me now so if someone could help out would be much appreciated
from tkinter import*
from operator import*
class App:
def __init__(self,master):#is the master for the button widgets
frame=Frame(master)
frame.pack()
self.addition = Button(frame, text="+", command=self.add)#when clicked sends a call back for a +
self.addition.pack()
def add(Y):
do("+")
def do(X):#will hopefully colaborate all of the inputs
cont, i = True, 0
store=["+","1","+","2","3","4"]
for i in range(5):
X=store[0+i]
print(store[0+i])
cont = False
if cont == False:
print(eval_binary_expr(*(store[:].split())))
def get_operator_fn(op):#allows the array to be split to find the operators
return {
'+' : add,
'-' : sub,
'*' : mul,
'/' : truediv,
}[op]
def eval_binary_expr(op1, num1, op2, num2):
store[1],store[3] = int(num1), int(num2)
return get_operator_fn(op2)(num1, num2)
root=Tk()
app=App(root)
root.mainloop()#runs programme
Generally speaking, every method in a class should take self as its first argument. The name self is just a convention. It is not a keyword in Python. However, when you call a method such as obj.add(...), the first argument sent to the method is the instance obj. It is a convention to call that instance self in the method definition. So all your methods need to be modified to include self as the first argument:
class App:
def __init__(self, master):#is the master for the button widgets
frame=Frame(master)
frame.pack()
self.addition = Button(frame, text="+", command=self.add)#when clicked sends a call back for a +
self.addition.pack()
def add(self):
self.do("+")
def do(self, X):
...
Note that when you call self.do("+"), inside the method do, X will be bound to "+". Later on in that method I see
X=store[0+i]
which will rebind X to the value store[i]. I don't know what you are trying to do here, but be aware that doing so means you've just lost the "+" value that was just passed in.

Categories