Sum of two Entry widgets in tkinter without buttons - python

I can't figure this out. I want to sum two entries and then put the sum in a label, without any buttons.
In my first example, I only got one entry and that works perfectly and it updates the label when typing.
In my first example I got two entries and I'm trying to pass both into the label (doesn't work).
In my third example, I'll tried to put the result in a list and them sum it and then trying to pass the result to the label, and that dosent work either.
I don't understand how I can pass one entry to the label, but I can't do it with two entries added together!
What to do??
Example one (one entry):
from tkinter import *
root = Tk()
var = DoubleVar()
var.set(float(0.000))
t1 = Entry(root, textvariable = var)
t1.pack()
l = Label(root, textvariable = var)
l.pack()
root.mainloop()
Example two (two entries):
from tkinter import *
root = Tk()
var1 = DoubleVar()
var1.set(float(0.100))
var2 = DoubleVar()
var2.set(float(0.200))
t1 = Entry(root, textvariable = var1)
t1.pack()
t2 = Entry(root, textvariable = var2)
t2.pack()
result = var1 + var2
l = Label(root, textvariable = result)
l.pack()
root.mainloop()
Example tree (two entries, with list): I get this error,
TypeError: unsupported operand type(s) for +: 'int' and 'DoubleVar'
How does I handle this??
from tkinter import *
root = Tk()
var1 = DoubleVar()
var1.set(float(0.100))
var2 = DoubleVar()
var2.set(float(0.200))
t1 = Entry(root, textvariable = var1)
t1.pack()
t2 = Entry(root, textvariable = var2)
t2.pack()
resultList = [var1, var2]
resultSum = sum(resultList)
l = Label(root, textvariable = resultSum)
l.pack()
root.mainloop()

To get the value from a Tkinter Variable you need to use its .get method. And you can use Tkinter's trace mechanism to watch the variables associated with your Entry widgets. Whenever the Entry values change the Label will automatically update.
import tkinter as tk
root = tk.Tk()
var1 = tk.DoubleVar()
t1 = tk.Entry(root, textvariable=var1)
t1.pack()
var2 = tk.DoubleVar()
t2 = tk.Entry(root, textvariable=var2)
t2.pack()
result = tk.DoubleVar()
l = tk.Label(root, textvariable=result)
l.pack()
# Put trace callbacks on the Entry DoubleVars
def set_label(name, index, mode):
result.set(var1.get() + var2.get())
var1.trace('w', set_label)
var2.trace('w', set_label)
# Setting the vars will trigger the trace
var1.set(0.25)
var2.set(0.5)
root.mainloop()

You need to invoke .get() to get the values of your DoubleVars. I don’t have access to tkinter at the moment (using Pythonista) to test this, but you should be able to do something like:
resultList = [var1.get(), var2.get()]
resultSum = sum(resultList)

Related

How to enable a disabled Button after filling Entry widgets?

I have 2 Entrys and one button. I want to make that button's state disabled until the two Entrys are filled in. How can I achieve that?
howManyStocksLabel = Label(root, text = "How many stocks do you want to evaluate?")
howManyStocksLabel.grid(row = 1, column = 0)
howManyStocksEntry = Entry(root, borderwidth = 3)
howManyStocksEntry.grid(row = 1, column = 1)
riskLabel = Label(root, text = "Enter risk %")
riskLabel.grid(row = 2, column = 0, sticky = 'w')
riskEntry = Entry(root, borderwidth = 3)
riskEntry.grid(row = 2, column = 1)
nextButton = Button(root, text = "Next!", width = 20, height = 2,state = DISABLED,
fg = 'green', bg = 'white',
command= lambda: myClick(riskEntry, howManyStocksEntry, var))
nextButton.grid(row = 4, column = 1)
I tried to check whether the entries are filled in or not by:
if(riskEntry.get() != ""):
....................
but it just doesn't work.
You need to check if the value is there after the user inputs it. Also, you can use tk.StringVar() as a text variable and trace it.
Here is an example:
import tkinter as tk
def check_entry(*args):
if r1.get() and r2.get():
b1.config(state='normal')
else:
b1.config(state='disabled')
root = tk.Tk()
r1 = tk.StringVar(master=root)
r2 = tk.StringVar(master=root)
e1 = tk.Entry(root, textvariable=r1)
e1.pack()
e2 = tk.Entry(root, textvariable=r2)
e2.pack()
b1 = tk.Button(root, text='Click Me!', state='disabled')
b1.pack()
r1.trace('w', check_entry)
r2.trace('w', check_entry)
root.mainloop()
You will need to use a binding on your entry widgets to check whether the user has entered anything into the entry or not.
This code will fire the check_entry function every time the user types in one of the entry boxes:
riskEntry.bind('<KeyRelease>', check_entry)
howManyStocksEntry.bind('<KeyRelease>', check_entry)
Then your check_entry function might look like this:
def check_entry(event): #event is required for all functions that use a binding
if riskEntry.get() and howManyStocksEntry.get():
nextButton.config(state=NORMAL)
else:
nextButton.config(state=DISABLED)
One way to do it would be to utilize the ability to "validate" their contents that Entry widgets support — see adding validation to an Entry widget — but make it check the contents of multiple Entry widgets and change the state of a Button accordingly.
Below shows how to do this via a helper class that encapsulates most of the messy details needed to make doing it relatively painless. Any number of Entry widgets can be "watched", so it scales well to handle forms consisting of many more than merely two entries.
from functools import partial
import tkinter as tk
from tkinter.constants import *
class ButtonEnabler:
""" Enable/disable a Button depending on whether all specified Entry widgets
are non-empty (i.e. contain at least one character).
"""
def __init__(self, button, *entries):
self.button = button
self.entries = entries
for entry in self.entries:
func = root.register(partial(self.check_entries, entry))
entry.config(validate="key", validatecommand=(func, '%P'))
def check_entries(self, this_entry, new_value):
other_entries = (entry for entry in self.entries if entry is not this_entry)
all_others_filled = all(entry.get() for entry in other_entries)
combined = bool(new_value) and all_others_filled
self.button.config(state=NORMAL if combined else DISABLED)
return True
root = tk.Tk()
howManyStocksLabel = tk.Label(root, text="How many stocks do you want to evaluate?")
howManyStocksLabel.grid(row=1, column=0)
howManyStocksEntry = tk.Entry(root, borderwidth=3)
howManyStocksEntry.grid(row=1, column=1)
riskLabel = tk.Label(root, text="Enter risk %")
riskLabel.grid(row=2, column=0, sticky='w')
riskEntry = tk.Entry(root, borderwidth=3)
riskEntry.grid(row=2, column=1)
nextButton = tk.Button(root, text="Next!", width=20, height=2, state=DISABLED,
fg='green', bg='white', disabledforeground='light grey',
command=lambda: myClick(riskEntry, howManyStocksEntry, var))
nextButton.grid(row=4, column=1)
enabler = ButtonEnabler(nextButton, howManyStocksEntry, riskEntry)
root.mainloop()

how to get the the value from the entry widget in tkinter in python3.6

I'm trying to get the data from the entry box.I'm not getting the use of those variables. It's showing me blank when I try to print the result. I tried using lambda but still not working. I'm new at this. Please show me where I'm wrong. I tried online but they are older version solutions.
def insertdata(E1):
print(E1)
e1 = StringVar()
L1 = Label(F1, text ="Serial No:",anchor = E)
L1.grid(row = 0 ,column = 0)
E1 = Entry(F1,textvariable = e1)
E1.grid(row = 0 ,column = 2, sticky = N)
v1 = e1.get()
Button (F2,text = "Paid",command=lambda:insertdata(v1)).pack(side= TOP)
This how to get content in entry widget and print. With the code you posted, you are doing a lot of wrong things; you cannot use pack and grid to postion your widget in the same window. Also never do this: Button (F2,text = "Paid",command=lambda:insertdata(v1)).pack(side= TOP), but always position your layout manager on the next line.
EXAMPLE
b = Button (F2,text = "Paid",command=lambda:insertdata(v1))
b.pack(side= TOP)
FULL CODE
from tkinter import *
def insertdata():
print(e1)
print(E1.get())
root = Tk()
L1 = Label( text="Serial No:", anchor=E)
L1.grid(row=0, column=0)
e1 = StringVar()
E1 = Entry( textvariable=e1)
E1.grid(row=0, column=2, sticky=N)
b = Button( text="Paid", command=insertdata)
b.grid(row=10, column=30)
root.mainloop()
You have set v1 to e1.get() before anything could be entered into the entry.
I tried the following code, and it works fine.
from tkinter import * # SHOULD NOT USE.
F1=Tk()
F2=Tk()
def insertdata(E1):
print(E1)
e1 = StringVar()
L1 = Label(F1, text ="Serial No:",anchor = E)
L1.grid(row = 0 ,column = 0)
E1 = Entry(F1,textvariable = e1)
E1.grid(row = 0 ,column = 2, sticky = N)
Button (F2,text = "Paid",command=lambda:insertdata(e1.get())).pack(side= TOP) # SHOULD NOT USE.

Issues figuring out how to update labels in Tkinter for my Python program

So I am writing a Python program in class that uses the Caesar cipher to take a users input and output it as cipher-text. Since i had a lot more time for this project I planned on giving it a GUI in Tkinter. But when I assign the resulted cipher-text to a label it won't display it and keeps it blank. I'm a noob to python and even more to Tkinter so I'm not too keen on being able to fix these issues myself. Here's the code:
import string
import collections
import random
import tkinter
from tkinter import *
from tkinter.ttk import *
root = Tk()
root.title("Encoder")
root.geometry("500x400")
def caesar(rotate_string, number_to_rotate_by):
upper = collections.deque(string.ascii_uppercase)
lower = collections.deque(string.ascii_lowercase)
upper.rotate(number_to_rotate_by)
lower.rotate(number_to_rotate_by)
upper = ''.join(list(upper))
lower = ''.join(list(lower))
return rotate_string.translate(str.maketrans(string.ascii_uppercase, upper)).translate(str.maketrans(string.ascii_lowercase, lower))
def callback():
print (code)
b = Button(root, text="get", width=10, command=callback)
b.pack()
var = StringVar()
e = Entry(root, textvariable = var)
e.pack()
our_string = e.get()
random_number = random.randint(1,25)
code = caesar(our_string, random_number)
l = Label(root, textvariable=code, anchor=NW, justify=LEFT, wraplength=398)
l.pack()
l.place(relx=0.5, rely=0.5, anchor=CENTER)
root.mainloop()
There are several issues with the code you've posted. First and foremost, your callback doesn't do anything besides print the code variable. You need to move your call to caesar and the associated code into the callback, like so
def callback():
global code
our_string = e.get()
random_number = random.randint(1, 25)
code.set(caesar(our_string, random_number))
The second issue that I see is that you need to use a StringVar as the textvariable argument in your Label constructor in order to get the label to update automatically. When all is said and done, my version of your code looks like
import string
import collections
import random
from tkinter import *
from tkinter.ttk import *
root = Tk()
root.title("Encoder")
root.geometry("500x400")
code = StringVar()
code.set('Hello')
def caesar(rotate_string, number_to_rotate_by):
upper = collections.deque(string.ascii_uppercase)
lower = collections.deque(string.ascii_lowercase)
upper.rotate(number_to_rotate_by)
lower.rotate(number_to_rotate_by)
upper = ''.join(list(upper))
lower = ''.join(list(lower))
return rotate_string.translate(str.maketrans(string.ascii_uppercase, upper)).translate(str.maketrans(string.ascii_lowercase, lower))
def callback():
global code
our_string = e.get()
random_number = random.randint(1, 25)
code.set(caesar(our_string, random_number))
b = Button(root, text="get", width=10, command=callback)
b.pack()
var = StringVar()
e = Entry(root, textvariable=var)
e.pack()
l = Label(root, textvariable=code, anchor=NW, justify=LEFT, wraplength=398)
l.pack()
l.place(relx=0.5, rely=0.5, anchor=CENTER)
root.mainloop()
This seems to do what you'd expect.

How can I dynamically create ttk widgets depending on the value entered in a ttk.entry box?

I am trying to make a GUI where as soon as the user inputs an integer into a ttk.entry field, that many checkbuttons need to appear below it. For example, if they put "5" into the entry widget, 5 check buttons need to appear below the entry field.
Edit:
What I ended up using:
self.number_of_stages = tk.IntVar()
self.check_box_dict={}
self.num_of_stages={}
self.stagetempvar={}
self.equipment_widgets={}
def centrifugal_compressor_widgets(self):
self.equipment_widgets.clear()
self.equipment_widgets["NumOfStagesLabelCentComp"]=tk.Label(self.parent, text="Number of Stages:", bg="white")
self.equipment_widgets["NumOfStagesLabelCentComp"].place(relx=0.5, y=260, anchor="center")
self.equipment_widgets["NumOfStagesEntryCentComp"]=ttk.Entry(self.parent, textvariable=self.number_of_stages)
self.equipment_widgets["NumOfStagesEntryCentComp"].place(relx=0.5, y=290, anchor="center")
def OnTraceCentComp(self, varname, elementname, mode):
for key in self.check_box_dict:
self.check_box_dict[key].destroy()
try:
if self.number_of_stages.get() <=15 :
i=1
self.stagetempvar.clear()
while i <= self.number_of_stages.get():
self.stagetempvar[i]=tk.StringVar()
self.stagetempvar[i].set("Closed")
self.check_box_dict[i]=ttk.Checkbutton(self.parent, text=i, offvalue="Closed", onvalue="Open",variable=self.stagetempvar[i])
self.check_box_dict[i].place(relx=(i*(1/(self.number_of_stages.get()+1))), y=360, anchor="center")
i+=1
except:
pass
take a look at the below and let me know what you think...
A very ugly, super basic example:
from Tkinter import *
root = Tk()
root.geometry('200x200')
root.grid_rowconfigure(0, weight = 1)
root.grid_columnconfigure(0, weight = 1)
win1 = Frame(root, bg= 'blue')
win1.grid(row=0, column=0, sticky='news')
number = IntVar()
entry = Entry(win1, textvariable = number)
entry.pack()
confirm = Button(win1, text = 'Press to create widgets...', command = lambda:create_widgets(number.get()))
confirm.pack()
def create_widgets(number):
for n in range(0,number):
Checkbutton(win1, text = 'Checkbutton number : %s' % n).pack()
root.mainloop()

Need assistance Tkinter in Python 2.7

I am writing a subnetting program in Python and I have come across a problem.
So far everything is working minus one thing. I dont know how to change a label in a method. in the code below, SubnetM is the variable being used to show the subnet mask. It is set to 0 by default but when you select HOSTS and enter 6 as Quantity. The 0 does not change to 255.255.255.248. PLEASE HELP
from Tkinter import *
SubnetM = 0
def beenclicked():
radioValue = relStatus.get()
return
def changeLabel():
if radio1 == 'HOSTS':
if Quantity == 6:
SubnetM = "255.255.255.248"
return
app = Tk()
app.title("SUBNET MASK CALCULATOR")
app.geometry('400x450+200+200')
labelText = StringVar()
labelText.set("WELCOME!")
label1 = Label(app,textvariable=labelText, height=4)
label1.pack()
relStatus = StringVar()
relStatus.set(None)
radio1 = Radiobutton(app, text="HOSTS", value="HOSTS", variable=relStatus, command=beenclicked).pack()
radio1 = Radiobutton(app, text="NETWORKS", value="NETWORKS", variable=relStatus, command=beenclicked).pack()
label2Text = StringVar()
label2Text.set("~Quantity~")
label2 = Label(app, textvariable=label2Text, height=4)
label2.pack()
custname = IntVar(None)
Quantity = Entry(app,textvariable=custname)
Quantity.pack()
label3Text = StringVar()
label3Text.set("Your Subnet Mask is...")
label3 = Label(app, textvariable=label3Text, height=4)
label3.pack()
label4Text = StringVar()
label4Text.set(SubnetM)
label4 = Label(app, textvariable=label4Text, height=4)
label4.pack()
button1 = Button(app, text="GO!", width=20, command=changeLabel)
button1.pack(padx=15, pady=15)
app.mainloop()
To fix your problem, make changeLabel like this:
def changeLabel():
# Get the radiobutton's StringVar and see if it equals "HOSTS"
if relStatus.get() == 'HOSTS':
# Get the entrybox's IntVar and see if it equals 6
if custname.get() == 6:
# Set the label's StringVar to "255.255.255.248"
label4Text.set("255.255.255.248")
Also, the .pack method of a Tkinter widget returns None. So, you should make the part that defines the radiobuttons like this:
radio1 = Radiobutton(app, text="HOSTS", value="HOSTS", variable=relStatus, command=beenclicked)
radio1.pack()
radio2 = Radiobutton(app, text="NETWORKS", value="NETWORKS", variable=relStatus, command=beenclicked)
radio2.pack()

Categories