How can I concatenate a string with a Tkinter Variable? - python

I've got a program that counts clicks of a button and displays them on a label. Instead of just showing the number, how can I add "Number of clicks: " before the value displayed? Preferably within the Label's widget arguments/options where textvariable=Total is defined.
Total = IntVar()
def Clicked():
Total.set(Total.get() + 1)
total = Label(root, textvariable=Total).pack()
click = Button(root, command=Clicked).pack()

Use separate variables to keep track of the number of clicks, and the string that represents the number of clicks.
from Tkinter import *
def Clicked():
global amount
amount += 1
Total.set("Number of clicks: {}".format(amount))
root = Tk()
Total = StringVar()
amount = 0
Label(root, textvariable=Total).pack()
Button(root, command=Clicked).pack()
root.mainloop()
Incidentally, never pack a widget and assign it to something on the same line - your variable will always be None. See Tkinter: AttributeError: NoneType object has no attribute get for more information.

tkinter requires that you use its own variable types for textvariable, so I would use a StringVar as your textvariable (you can update the text property of some items directly, but different tkinter objects may have different methods for doing this, and it can get confusing). Here's how you can update a StringVar to show your counts.
root = tk.Tk()
tk.IntVar(value='1')
sv = tk.StringVar()
sv.set('clicks = ' + str(iv.get()))
>>> sv.get()
'clicks = 1'

Related

Radiobutton not updating values when clicked in python with tkinter

This is my first attempt at a GUI. Right now I just want to be able to click a radiobutton and make it print the value I assigned to the button. However, var.get() isn't giving me anything. I tried it with IntVar (and had my values as 1 and 2 instead of "proton" and "electron") and var.get() would just give me 0. With StringVar it gives nothing (nothing prints when choosecharge is called by the radiobutton). I've tried reading stuff about radiobuttons and I wrote my code based on how I saw it done and it successfully creates the radiobuttons, but the whole point is to be able to use their values when clicked.
import tkinter as tk
def choosecharge():
print(var.get())
root = tk.Tk()
var = tk.StringVar()
proton = tk.Radiobutton(root, text = "proton", variable = var, value = "proton", command = choosecharge)
proton.pack( )
electron = tk.Radiobutton(root, text="electron", variable = var, value= "electron", command = choosecharge)
electron.pack( )
root.mainloop()
I have taken a slightly different approach to accomplish this task.
I created a dictionary of the integer radiobutton values as key and
the string that you wish to print as value.
Used a label widget to print the string in the GUI
import tkinter as tk
root = tk.Tk()
# define an IntVar
var = tk.IntVar()
# create a dictionary of key:value pair as radiobutton_value: str_name_to_print
values = {1: "proton", 2: "electron"}
# instantiate a label widget
lbl = tk.Label(root)
def choosecharge():
# update the label widgets using the dictionary
lbl.config(text=values[var.get()])
proton = tk.Radiobutton(root, text="proton", variable=var, value=1, command=choosecharge)
proton.pack(anchor=tk.W)
electron = tk.Radiobutton(root, text="electron", variable=var, value=2, command=choosecharge)
electron.pack(anchor=tk.W)
# pack the label widget below the two radiobuttons
lbl.pack()
root.mainloop()
Screenshot
I have commented the lines in the code for better understanding. I hope this solution helps you.

how do I create entry fields and buttons to get the content from the entry field using iteration in tkinter for python?

I'm trying to make a tkinter GUI with a certain amount of buttons and entry fields that is specified by the user, so in this code below for example if the user specifies the variable number to be 3 I want there to be 3 entry boxes and , and I want to set it up so that if I type a value into the first field and click the button next to it, I want that button to read the value from the entry field next to it. I also need to assign each entry field to a variable that will be created through the same iterative loop. However, I'm having difficulty especially in regards to mapping the buttons to the entry fields, as I always seem to run up against an error with the text "AttributeError: 'NoneType' object has no attribute 'get'". Would anyone be able to either fix my code or help me find an alternative solution to the problem? Sorry if the description's a bit confusing.
This is different from just a problem of just getting the contents of the entry widget as I need it to create a certain amount of entry widgets and buttons using iteration, and the question that my question has been marked a duplicate of doesn't explain how to iteratively map each entry field to each button. For example, if I enter 3 as the variable, I need the program to create entry field 1, entry field 2 and entry field 3 and button 1, button 2 and button 3 and then map each button to its respective entry field using iteration.
I've tried using dictionaries, but this doesn't seem to help much.
import tkinter as tk
root = tk.Tk()
number = 3
d={}
def callBack():
print(d["E{0}".format(i)].get())
return
for i in range(0,number):
d["E{0}".format(i)] = tk.Entry(root)
d["E{0}".format(i)].grid(row=i, column=0)
d["B{0}".format(i)] = tk.Button(root, text="test", command=callBack)
d["B{0}".format(i)].grid(row=i, column=1)
The solution to "'NoneType' object has no attribute 'get'" has been asked probably a hundred times on this site, and the answer is always the same.
In python, when you do x = y().z(), x will be given the value of z(). In the case of x=tk.Entry(...).grid(...), x will be None because grid(...) always returns None. The solution is to always call grid or pack or place separate from when you create a widget.
You also claim you are having problems with dictionaries, but I don't see any problem in your code other than you are making it more difficult than necessary. You can directly use i as an index without having to build up a string for the index. If you need to keep track of both buttons and entries, I recommend two variables rather than one.
Part of the problem may also have to do with the fact you're trying to do something very odd in your command. You're trying to call the get method of the entry, but that's pointless since it simply returns a value that gets thrown away. In almost all cases, the correct solution is to write a proper function rather than trying to squeeze functionality into a lambda.
Example:
def handle_click(i):
entry = entries[i]
print("the value is {}".format(entry.get()))
buttons = {}
entries = {}
for i in range(0,number):
entry = tk.Entry(root)
button = tk.Button(root, text="test", command=lambda i=i: handle_click(i))
buttons[i] = button
entries[i] = entry
entry.grid(row=i, column=0)
button.grid(row=i, column=1)
You need to save the Entry and Button before calling grid:
import tkinter as tk
number = 3
root = tk.Tk()
def get_on_click(widget_dict, entry_name):
def on_click():
result = widget_dict[entry_name].get()
print("%s = %s" % (entry_name, result))
return result
return on_click
d = dict()
for i in range(0, number):
entry_name = "E{0}".format(i)
button_name = "B{0}".format(i)
print(entry_name, button_name)
d[entry_name] = tk.Entry(root)
d[entry_name].grid(row=i, column=0)
d[button_name] = tk.Button(root, text="test", command=get_on_click(d, entry_name))
d[button_name].grid(row=i, column=1)
root.mainloop()
This should help you get started.
In your comment, you ask how to save the value in the Entry. I would create a class to handle everything:
import tkinter as tk
number = 3
root = tk.Tk()
class EntryButton(object):
def __init__(self, root, number):
self.number = number
self.entry = tk.Entry(root)
self.button = tk.Button(root, text="test", command=self.on_click)
self.entry.grid(row=number, column=0)
self.button.grid(row=number, column=1)
self.value = None
def on_click(self):
self.value = self.entry.get()
storage = dict()
for i in range(0, number):
storage[i] = EntryButton(root, i)
root.mainloop()
for i in range(0, number):
value = storage[i].value
print(f"storage[{i}] = {value}")
As you can see, this eliminates a lot of extra work.
For get text from entry
Entry.get("1.0", "end-1c")
# 1.0 for get first line.
# end-1c for if last letter space, this deletes it.
More info

Tkinter: AttributeError using .get()

I am trying to retrieve a variable from a Tkinter Wiget but I am running into this error message:
AttributeError: 'int' object has no attribute 'get'
Here is the widget code
JobNEntry = tkinter.Entry(menu, textvariable = tk.IntVar(JobNo))
JobNEntry.grid(row=2, column=2, sticky="W")
Here is the call code
JobNo=JobNo.get()
Also I need to know if the variable JobNo is writable to a file.
Thanks in advance
The get() method is part of several widgets in tkinter and is not something that you can use on a normal int or str object. get() must be called on a variable that is a widget object that has a get() method, like Entry.
Its likely you need to do:
JobNEntry.get()
This will get the current value from the entry field as a string.
If you want to save the value of that string you can. There are several tutorials on Stack Overflow and the web that go into detail on how to save a string to a file.
Looking at the code you have shown us, it's possible you have not created your IntVar() correctly.
Make sure you define the IntVar() first then set that variable as the textvariable.
Something like this:
JobNo = tk.IntVar()
JobNEntry = tkinter.Entry(menu, textvariable = JobNo)
The attribute error might be because you havnt already initialized the variable JobNo as an 'IntVar'
This is the code i have come up with :
import tkinter as tkinter
menu=tkinter.Tk()
JobNo=tkinter.IntVar()
JobNEntry = tkinter.Entry(menu, textvariable = JobNo)
JobNEntry.grid(row=2, column=2, sticky="W")
JobNo=JobNo.get()
menu.mainloop()
You need to initialize JobNo as an Integer Variable using IntVar()
JobNo=tkinter.IntVar()
And then use it in the Entrybox.
If you had some string to add to the entry, you should initialise as StringVar()
Also when you initialize, make sure you do it after opening the Tk window.(here i put it after menu=tkinter.Tk())
Something like this:
from tkinter import *
from tkinter import ttk
def save_job_no():
try:
n = job_no.get()
except TclError:
status.config(text = "This is not an integer")
return False
status.config(text="")
f = open("my_file.txt", "w")
f.write(str(n))
return True
root = Tk()
job_no = IntVar()
entry = ttk.Entry(root, width = 30, textvariable = job_no)
entry.grid()
label = ttk.Label(root, textvariable = job_no)
label.grid()
status = ttk.Label(root)
status.grid()
button = ttk.Button(root, text = "Write to a file", command = save_job_no)
button.grid()
root.mainloop()

Tkinter: Link an Entry Widget to a Button to a Function

I am new to Tkinter and not to sure how to proceed. I am trying to link a function that I define to a entry widget that is activated by a button. but I can't figure out how to get the three to communicate to each other. I would like it to print as well as return to the script so that I can be used in another function. This is what I have so far:
import Tkinter as tk
def TestMath(x):
calculate = x + 4
print calculate
return calculate
root = tk.Tk()
entry = tk.Entry(root)
value = entry.get()
number = int(value)
button = tk.Button(root, text="Calculate")
calculation = TestMath(number)
root.mainloop()
Button calls function assigned to command= (it has to be "function name" without () and arguments - or lambda function)
TestMath assigns calculation to global variable result and other functions can have access to that value.
import Tkinter as tk
def TestMath():
global result # to return calculation
result = int(entry.get())
result += 4
print result
result = 0
root = tk.Tk()
entry = tk.Entry(root)
entry.pack()
button = tk.Button(root, text="Calculate", command=TestMath)
button.pack()
root.mainloop()
Function called by button don't have to return value because there is no object which could receive that value.

Dynamically generated list of checkboxes in Tkinter only returns 0s

I am writing a small gui with Tkinter in python 2,7. At some point I call a function that creates a popup window that is populated by a number of checkboxes, the number of checkboxes is defined by the attributes variable.
def attribute_select(attributes):
popup = tk.Tk()
popup.wm_title("Attribute selection")
label = ttk.Label(popup, text="Please select which of the following \n attributes will undergo k-anonymity.",
font=NORMAL_FONT)
label.pack(side="top", fill="x", pady=10)
def read_status(key):
var_obj = var.get(key)
print "key is:", key
print "var_obj.get() is:", var_obj.get()
def leave_mini():
popup.destroy()
var = dict()
count = 1
for child in range(attributes):
var[child] = tk.IntVar()
chk = tk.Checkbutton(popup, text='Attribute: '+str(count), variable=var[child], justify="left", onvalue=1,
offvalue=0, command=lambda key=child: read_status(key))
count += 1
chk.pack()
print var
exit_button = ttk.Button(popup, text="OK", command=leave_mini)
exit_button.pack()
popup.mainloop()
Everything runs just fine but when I try to check one of the boxes the variable value doesn't change the printout every time is: [ key is: 0 var_obj.get() is: 0 ] or [ key is: 5 var_obj.get() is: 0 ]. So the key is proper for every box but the variable doesn't change. I'm sure it's a simple fix I just can't see it... any ideas?
You must not create more than one instance of Tk. By creating an instance in attribute_select I must assume you've create the "real" root window somewhere else. One of the side effects of creating more than one instance of Tk is that your tkinter variables (IntVar, etc) don't behave the way you expect them to.
If you need popup windows, create instances of Toplevel.

Categories