I am in the process of learning basic Python. I am currently attempting to create a simple calculator program that only has addition and subtraction. I have one issue though. I am not sure how I would add text to my Python label upon button press. Right now, upon pressing the '1' button, my program will change the display label to the text "1". However, I want my program to add text, not set it.
For example, if I press 'button 1' 5 times, it currently will reset the label text 5 times and will result with a single 1. I want it to add the number to the label upon press, not replace.
Current Result after pressing button 5 times: 1
Requested result after pressing button 5 times: 11111
Here is my current code for the program. If anything is unclear, just ask; thanks.
from tkinter import *
window = Tk()
# Creating main label
display = Label(window, text="")
display.grid(row=0, columnspan=3)
def add_one():
display.config(text='1')
# Creating all number buttons
one = Button(window, text="1", height=10, width=10, command=add_one)
two = Button(window, text="2", height=10, width=10)
three = Button(window, text="3", height=10, width=10)
four = Button(window, text="4", height=10, width=10)
five = Button(window, text="5", height=10, width=10)
six = Button(window, text="6", height=10, width=10)
seven = Button(window, text="7", height=10, width=10)
eight = Button(window, text="8", height=10, width=10)
nine = Button(window, text="9", height=10, width=10)
zero = Button(window, text="0", height=10, width=10)
# Placing all number buttons
one.grid(row=1, column=0)
two.grid(row=1, column=1)
three.grid(row=1, column=2)
four.grid(row=2, column=0)
five.grid(row=2, column=1)
six.grid(row=2, column=2)
seven.grid(row=3, column=0)
eight.grid(row=3, column=1)
nine.grid(row=3, column=2)
# Creating all other buttons
add = Button(window, text="+", height=10, width=10)
subtract = Button(window, text="-", height=10, width=10)
equal = Button(window, text="=", height=10, width=10)
# Placing all other buttons
add.grid(row=4, column=0)
subtract.grid(row=4, column=1)
equal.grid(row=4, column=2)
window.mainloop()
You should use a StringVar for this. And your callback needs to get the current contents of the StringVar, modify it, and use the modified string to set the new value of the StringVar. Like this:
import tkinter as tk
window = tk.Tk()
# Creating main label
display_text = tk.StringVar()
display = tk.Label(window, textvariable=display_text)
display.grid(row=0, columnspan=3)
def add_one():
s = display_text.get()
s += '1'
display_text.set(s)
one = tk.Button(window, text="1", height=10, width=10, command=add_one)
one.grid(row=1, column=0)
window.mainloop()
BTW, you should try to make your program a little more compact by using for loops to create and lay out your buttons, in accordance with the DRY principle.
Also, it's not a good idea to use from tkinter import *. It imports over 130 names into your namespace, making it easy to create name collisions if you accidentally use a Tkinter name for one of your own variables or functions.
You can define add_one like the following, to first get the existing value and then append a new value to it:
def add_one():
current_value = display.cget("text")
new_value = current_value + "1"
display.config(text=new_value)
Is this what you're looking for:
from tkinter import *
root = Tk()
var = StringVar()
def f1():
var.set(" ")
var.set("1")
def f2():
var.set(" ")
var.set("2")
label = Label(root, textvariable=var)
label.pack()
button1 = Button(root, text="One", command=f1)
button1.pack()
button2 = Button(root, text="Two", command=f2)
button2.pack()
?
Related
I want to take user input and output it inside GUI ...
my code
from tkinter import *
root = Tk()
root.geometry("644x344")
def printSomething():
label = Label(root, text="???")
label.grid(row=1, column=2)
ok=Label(root, text="Type your name").grid(row=2,column=1)
entryvalue = StringVar()
entry= Entry(root, textvariable=entryvalue)
entry.grid(row=2, column=2)
button = Button(root, text="Print Me", command=printSomething)
button.grid(row=3, column=2)
root.mainloop()
To get the text from an input box, use inputbox.get(). Also, don't set the ok variable to Label(root, text="Type your name").grid(row=2,column=1). This will be set as NoneType, so do
ok = Label(root, text="Type your name").grid(row=2,column=1)
ok.grid(row=2, column=1)
Here is your code:
from tkinter import *
root = Tk()
root.geometry("644x344")
def printSomething():
label = Label(root, text=entry.get())
label.grid(row=1, column=2)
ok=Label(root, text="Type your name")
ok.grid(row=2,column=1)
entryvalue = StringVar()
entry= Entry(root, textvariable=entryvalue)
entry.grid(row=2, column=2)
button = Button(root, text="Print Me", command=printSomething)
button.grid(row=3, column=2)
root.mainloop()
First thing, In order to accept and display the output on the screen you have to use either Label widget or Canvas Text. Since your code is not updating the Label widget thus I am here doing what you want to do.
First, create a Label widget in the main window,
Get the user input by using.get() method,
print and display the user input.
from tkinter import *
root = Tk()
root.geometry("644x344")
def printSomething():
label.config(text=entry.get())
ok=Label(root, text="Type your name")
ok.grid(row=2,column=1)
entryvalue = StringVar()
entry= Entry(root, textvariable=entryvalue)
entry.grid(row=2, column=2)
button = Button(root, text="Print Me", command=printSomething)
button.grid(row=3, column=2)
#Create a Label to print the Name
label= Label(root, text="", font= ('Helvetica 14 bold'), foreground= "red3")
label.grid(row=1, column=2)
root.mainloop()
I'm starting to learn Tkinter library and I have a problem...
I use grid to set my window the way I want but I can't figure out how I can set the width of the entry widget the same as the text widget.
When I put the same number, I don't have the same width anyway...
Here is my code :
from tkinter import *
def click():
try:
output.delete(0.0,END)
entered_text=entry.get()
output.insert(END, entered_text)
except:
output.insert(END, "")
def reset():
output.delete(0.0,END)
entry.delete(0,END)
if __name__ == '__main__':
window = Tk()
window.title("TEST")
window.geometry("500x500")
Label (window, text="Nombre de palettes :").grid(row=0, sticky=W)
Label (window, text="Prix :").grid(row=1, sticky=W)
entry = Entry (window)
entry.grid(row=0, column=2)
output = Text(window, width=8, heigh=1, wrap=WORD)
output.grid(row=1, column=2)
accepter=Button(window, text="Accepter", width=6, command=click)
accepter.grid(row=2, column=0)
restart = Button(window, text="Reset", width=6,command=reset)
restart.grid(row=2, column=1)
fin = Button(window, text="Quitter", width=6,command=window.destroy)
fin.grid(row=2, column=2)
window.grid_columnconfigure(4, minsize=100)
window.mainloop()
Thank you in advance.
One way is to expand the widgets to fill the cell:
entry = Entry(window)
entry.grid(row=0, column=2, sticky=E+W, padx=10)
output = Text(window, width=8, heigh=1, wrap=WORD)
output.grid(row=1, column=2, sticky=E+W, padx=10)
Where sticky=E+W fills the cell horizontally, and then I add some padding padx=10 to get a distance from the cell limits.
If one of the widgets always is bigger you can let that widget determine the cell width and then just expand the other widget.
So basically I am practising using Tkinter and I was going to make a little clicker game based on anime. I have researched loads, however, no matter what I try the text saying how many RC cells I have won't show anything at all. please keep it simple as I'm still new to coding.
from tkinter import *
rcc=1
x=1
#click function
def click():
global rcc
rcc=rcc+1
return rcc
while x==1:
rccc=str(rcc)
window=Tk()
window.title("my click game boi")
rc=StringVar()
rc.set=(rccc)
window.configure(background="black")
##### my photo
photo1=PhotoImage(file="kanekipic.gif")
Label (window, image=photo1, bg='black') .grid(row=0, column=0, sticky=E)
Button(window, text="eat", width=3, command=click) .grid(row=3, column=0,
sticky=W)
Label1=Label(window, textvariable=rc, bg="red", fg="white") .grid(row=1, column=0, sticky=S)
print (rcc)
window.mainloop()
The best solution (in the sense that it preserves the desired goal and is "kept simple"), I came up with is:
#!/usr/bin/env python3
from tkinter import *
rcc = 1
def click():
global rcc
rcc += 1
rc.set(rcc)
print('rcc was increased to {}'.format(rcc))
if __name__ == '__main__':
window = Tk()
window.title("my click game boi")
window.configure(background='black')
rc = IntVar()
photo1 = PhotoImage(file="kanekipic.gif")
Label(window, image=photo1, bg='black').grid(row=0, column=0, sticky=E)
Button(window, text="eat", width=3, command=click).grid(row=3, column=0, sticky=W)
Label(window, textvariable=rc, bg="red", fg="white").grid(row=1, column=0, sticky=S)
window.mainloop()
Whenever you click on the eat button, the counter will be increased.
Please Help! I'm at my wits end over here... I am new to learning Python and tkinter and I have not found anyone trying to do what I am, so I keep trying different people's answers and nothing is working. I can't understand the docs, and every tutorial I find is not quite exactly what I need to do, so I end up with irrelevant code bits that just lead to more problems.
I want to build a GUI for a touchscreen program for a Raspberry Pi that will allow me to program a relay to turn on for "x" seconds, then turn off for "y" seconds, then repeat forever until I stop it. The touchscreen needs to have large buttons for each of the numbers 0 - 9, a button to clear the values, buttons to confirm each value once it has been input in the entry box, a button to start the cycle, and a button to exit. There also needs to be 2 entry boxes, one for "On", and one for "Off", so that the user can see the numbers they have entered for each value. This is what is messing me up. I can get it to work for one entry box, but not two.
Please someone tell me what is wrong. I don't know how to tell each button to place its value only in the entry field that has focus. I can only figure out how to tell it to input in one entry or the other, regardless of which has focus.
I also need the numbers to appear in the entry boxes in the correct sequence, so that when you type a "3" and then a "0", the program reads "30". Right now it is producing "03".
Here's the code. I have some things commented out currently, and yes, I know it's ugly:
#!/usr/bin/env python
try:
# for Python 2
from Tkinter import *
except ImportError:
# for Python 3
from tkinter import *
import ttk as ttk
import RPi.GPIO as GPIO
import time
GPIO.setwarnings(False)
GPIO.setmode(GPIO.BCM)
GPIO.setup(4, GPIO.OUT)
GPIO.setup(4, GPIO.LOW)
running = True
def water():
go.grid(column=4, row=3, rowspan=6, columnspan=6, sticky=W)
def go():
running = True
x = on.get()
y = off.get()
y = float(y)
x = float(x)
if running:
GPIO.output(4, False)
print("Off")
time.sleep(y)
GPIO.output(4, True)
print("On")
time.sleep(x)
root.after(10, go)
def clear():
on.set('')
off.set('')
global running
running = False
go.grid_forget()
on_entry.focus()
def select(value):
if on_entry.focus():
on_entry.set(value)
elif off_entry.focus():
off_entry.set(value)
def geton():
on_entry.get()
off_entry.focus()
def getoff():
off_entry.get()
water()
#this is the PROBLEM!!!!
def set_text(text):
on_entry.insert(0,text)
#buttons = ['1','2','3','4','5','6','7','8','9','0']
#varRow = 5
#varColumn = 0
root = Tk()
root.geometry("740x480+0+0")
root.title("Waterboy")
#need to make this fullscreen
mainframe = Frame(root)
mainframe.grid(column=0, row=0, sticky=(N, W, E, S))
mainframe.columnconfigure(0, weight=1)
mainframe.rowconfigure(0, weight=1)
go = Button(mainframe, text="GO", command=go, bg="green", width=6, height=11)
#seconds on and off
on = StringVar()
off = StringVar()
on_entry = Entry(mainframe, width=8, textvariable=on)
on_entry.grid(column=2, row=1, sticky=(W, E))
off_entry = Entry(mainframe, width=8, textvariable=off)
off_entry.grid(column=2, row=2, sticky=(W, E))
on_entry.focus_set()
onok = Button(mainframe, text="OK", command=geton, bg="white", width=6, height=1)
onok.grid(column=4, row=1, sticky=W)
offok = Button(mainframe, text="OK", command=getoff, bg="white", width=6, height=1)
offok.grid(column=4, row=2, sticky=W)
reset = Button(mainframe, text="Reset Values", command=clear, bg='yellow', width=16, height=2)
reset.grid(column=0, row=7, sticky=W)
adios = Button(mainframe, text="EXIT", command=exit, bg="red", width=16, height=2)
adios.grid(column=2, row=7, sticky=W)
secon = ttk.Label(mainframe, text="Input # Seconds Water ON and press 'OK' -->", width=36)
secon.grid(column=0, row=1, columnspan=2)
secoff = ttk.Label(mainframe, text="Input # Seconds Water OFF and press 'OK' -->", width=36)
secoff.grid(column=0, row=2, columnspan=2)
one = Button(mainframe, text="1", width=16, height=2, command=lambda:set_text("1")
one.grid(column=0, row=4, sticky=W)
two = Button(mainframe, text="2", width=16, height=2, command=lambda:set_text("2")
two.grid(column=1, row=4, sticky=W)
three = Button(mainframe, text="3", width=16, height=2, command=lambda:set_text("3")
three.grid(column=2, row=4, sticky=W)
four = Button(mainframe, text="4", width=16, height=2, command=lambda:set_text("4")
four.grid(column=0, row=5, sticky=W)
five = Button(mainframe, text="5", width=16, height=2, command=lambda:set_text("5")
five.grid(column=1, row=5, sticky=W)
six = Button(mainframe, text="6", width=16, height=2, command=lambda:set_text("6")
six.grid(column=2, row=5, sticky=W)
seven = Button(mainframe, text="7", width=16, height=2, command=lambda:set_text("7")
seven.grid(column=0, row=6, sticky=W)
eight = Button(mainframe, text="8", width=16, height=2, command=lambda:set_text("8")
eight.grid(column=1, row=6, sticky=W)
nine = Button(mainframe, text="9", width=16, height=2, command=lambda:set_text("9")
nine.grid(column=2, row=6, sticky=W)
zero = Button(mainframe, text="0", width=16, height=2, command=lambda:set_text("0")
zero.grid(column=1, row=7, sticky=W)
#for child in mainframe.winfo_children(): child.grid_configure(padx=4, pady=4)
#root.bind('<Return>', go)
#for button in buttons:
# command = lambda x=button: select(x)
# Button(mainframe, text=button, width=5, bg="white", command = command).grid(row = varRow, column=varColumn)
# varColumn += 1
# if varColumn > 2 and varRow == 4:
# varColumn = 0
# varRow += 1
# if varColumn > 2 and varRow == 5:
# varColumn = 0
# varRow += 1
# if varColumn > 2 and varRow == 6:
# varColumn = 0
# varRow += 1
root.mainloop()
You can use the method focus_get on the root window to get the widget that has focus. You can then insert text using that widget. You can specify the special index of "end" to have the text inserted at the end of the widget.
For example:
def set_text(text)
widget = root.focus_get()
widget.insert("end", text)
Of course, you'll want to do some validation to make sure that the widget is a text or entry widget.
Also, be careful with using ttk -- the default behavior of ttk button widgets is to steal the keyboard focus.
This question already exists:
"Unexpected EOF while parsing" in calculator
Closed 8 years ago.
I have a calculator in Python 3 but for some reason my code doesn't work. It works fine until I press the "=" button to calculate my thing (using tkinter for the gui). Here is my code (it is quite long, sorry for that, it is just a part from my code)
from tkinter import *
from tkinter.ttk import *
def SMATH():
#PUT TEXT IN ENTRY FUNCTION
def puttext(text):
sm_ent.insert(0,text)
return
#CLEAR THE ENTRY FUNCTION
def cleartext():
sm_ent.delete(0, END)
return
#GET THE OUTCOME FUNCTION
def Coutcome():
calc = caltext.get()
answer = eval(calc)
sm_ent = Entry(e_frame, textvariable=caltext, text=answer)
smathW = Tk()
smathW.title("Simple Math")
smathW.resizable(0,0)
smathW.wm_iconbitmap('icon.ico')
def quitSmath():
smathW.destroy()
#ENTRY FRAME
e_frame = Frame(smathW)
e_frame.pack()
#BUTTONS FRAME
b_frame = Frame(smathW)
b_frame.pack()
#ENTRY
caltext= StringVar()
sm_ent = Entry(e_frame, textvariable=caltext)
sm_ent.pack(fill=Y)
#LABEL
sm_inf = Label(smathW, text="Here is the Simple Math mode from CalfoWin")
sm_inf.pack()
#BUTTON 7
sm_butt0 = Button(b_frame, text="7", command=lambda: puttext('7'))
sm_butt0.grid(row=1, column=0)
#BUTTON 8
sm_butt1 = Button(b_frame, text="8", command=lambda: puttext('8'))
sm_butt1.grid(row=1, column=1)
#BUTTON 9
sm_butt2 = Button(b_frame, text="9", command=lambda: puttext('9'))
sm_butt2.grid(row=1, column=2)
#BUTTON 4
sm_butt3 = Button(b_frame, text="4", command=lambda: puttext('4'))
sm_butt3.grid(row=2, column=0)
#BUTTON 5
sm_butt4 = Button(b_frame, text="5", command=lambda: puttext('5'))
sm_butt4.grid(row=2, column=1)
#BUTTON 6
sm_butt5 = Button(b_frame, text="6", command=lambda: puttext('6'))
sm_butt5.grid(row=2, column=2)
#BUTTON 1
sm_butt6 = Button(b_frame, text="1", command=lambda: puttext('1'))
sm_butt6.grid(row=3, column=0)
#BUTTON 2
sm_butt7 = Button(b_frame, text="2", command=lambda: puttext('2'))
sm_butt7.grid(row=3, column=1)
#BUTTON 3
sm_butt8 = Button(b_frame, text="3", command=lambda: puttext('3'))
sm_butt8.grid(row=3, column=2)
#BUTTON 0
sm_butt9 = Button(b_frame, text="0", command=lambda: puttext('0'))
sm_butt9.grid(row=4, column=0)
#BUTTON KOMMA
sm_buttKomma = Button(b_frame, text=".", command=lambda: puttext('.'))
sm_buttKomma.grid(row=4, column=1)
#BUTTON EQUALSIGN!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
sm_buttEsign = Button(b_frame, text="=", command=Coutcome())
sm_buttEsign.grid(row=4, column=2)
#BUTTON ADDITION
sm_buttPlus = Button(b_frame, text="+", command=lambda: puttext('+'))
sm_buttPlus.grid(row=2, column=3)
#BUTTON SUBTRACKTION
sm_buttMin = Button(b_frame, text="-", command=lambda: puttext('-'))
sm_buttMin.grid(row=3, column=3)
#BUTTON DIVISION
sm_buttDiv = Button(b_frame, text="/", command=lambda: puttext('/'))
sm_buttDiv.grid(row=3, column=4)
#BUTTON MULTIPLICATION
sm_buttMult = Button(b_frame, text='x', command=lambda: puttext('*'))
sm_buttMult.grid(row=2, column=4)
#BUTTON CLEAR
sm_buttClear = Button(b_frame, text="Clear", command=lambda: cleartext())
sm_buttClear.grid(row=1, column=3)
#BUTTON QUIT
sm_buttquit = Button(b_frame, text="Quit", command=lambda: quitSmath())
sm_buttquit.grid(row=1, column=4)
You use command = Coutcome() which passes the return value of Coutcome as the funtion to call when the button is pressed. So what happens now is that Coutcome is called when the button is created, and caltext is still empty. This means that you are running eval(''), which gives you the error you are seeing.
This is not what you want, you want Coutcome to be called when the button is pressed. So You should pass the function name, without parentheses, as the command
sm_buttEsign = Button(b_frame, text="=", command=Coutcome)
For your quit and clear buttons you should do the same thing, get rid of the parentheses and the lambda. The reason you need to use lambda sometimes is because when you have to leave out the parentheses, you can't pass variables to the command. When you don't need to pass variables, the lambda is superfluous.
In addition, you should be careful using eval. With the wrong input, it can be dangerous. So watch out with letting users input stuff to eval without proper restrictions.