tkinter entry fields not updating using .insert - python

I'm trying to create a GUI and I am having trouble getting read only entry fields to insert a value. I've tried using a text value and this didn't insert anything into the field.
here is the function:
def calculateFinalCMD():
global planetInfo
global getDestinationNum
displayfc1.grid(row=14, column=2)
displayfc1.insert(0, ((100 - int(crewInfo[0][1])) * planetInfo[getDestinationNum][1]))
displayfc2.grid(row=15, column=2)
displayfc2.insert(0, ((100 - int(crewInfo[1][1])) * planetInfo[getDestinationNum][1]))
displayfc3.grid(row=16, column=2)
displayfc3.insert(0, ((100 - int(crewInfo[2][1])) * planetInfo[getDestinationNum][1]))
displayfc4.grid(row=17, column=2)
displayfc4.insert(0, ((100 - int(crewInfo[3][1])) * planetInfo[getDestinationNum][1]))
displayms1.grid(row=18, column=2)
displayms1.insert(0, ((150 - int(crewInfo[4][1])) * planetInfo[getDestinationNum][1]))
displayms2.grid(row=19, column=2)
displayms2.insert(0, ((150 - int(crewInfo[5][1])) * planetInfo[getDestinationNum][1]))
Here are the entry fields which are separate from the function, getDestinationNum is updated by another entry field earlier in the code.
getDestinationNum = 0
displayfc1 = Entry(root, state="readonly")
displayfc2 = Entry(root, state="readonly")
displayfc3 = Entry(root, state="readonly")
displayfc4 = Entry(root, state="readonly")
displayms1 = Entry(root, state="readonly")
displayms2 = Entry(root, state="readonly")
Any ideas on how anything could be changed or if the code is wrong? thanks!

This is not a minimal reproducible example. Something like this would have better explained your problem.
from tkinter import Tk, Entry
root = Tk()
my_entry = Entry(root, state='readonly')
my_entry.grid(row=0, column=0)
my_entry.insert(0, 500) # does not work
root.mainloop()
The problem is that your Entry widget is read only and cannot be updated.
We can get around that by waiting until we have set a value and use the configure method to update the state after the fact.
from tkinter import Tk, Entry
root = Tk()
my_entry = Entry(root)
my_entry.grid(row=0, column=0)
my_entry.insert(0, 500)
my_entry.configure(state='readonly')
root.mainloop()
There are some other things that could be improved with your code like relegating your calculations to a helper function, having your entries in arrays, and setting your entries in a loop.
This is just an example as I don't have access to what's inside your variables.
# This makes it much easier to follow the logic
# of your calculation
def calculate(multiplier, crew, planet):
return (multiplier - int(crew[1])) * planet[1]
multipliers = [100, 100, 100, 100, 150, 150]
# you could just append your entries to an array when creating them
# rather than add them here
entries = [displayfc1,
displayfc2,
displayfc3,
displayfc4,
displayms1,
displayms2
]
# zipping them up allows you to iterate through all
# of them at once
for entry, mult, crew, row in zip(entries,
multipliers,
crewInfo,
range(14, 20)
):
entry.grid(row=row, column=2)
entry.insert(0, calculate(mult, crew, planetInfo[getDestinationNum]))
entry.configure(state='readonly')

Related

One of my variables is being printed but the other is not in tkinter Entry boxes

I'm trying to create a function in tkinter where I can print out what the user writes in a Entry box. I'm able to print out ask_an_entry_get, but when I try to print what_is_answer_entry_get
, I get nothing my empty spaces.
Please find out the problem here. Also I'm using the Entry widget, along with the get() function, to get input from the user.
def answer_quizmaker_score():
print(ask_an_entry_get)
print(what_is_answer_entry_get)
I made a lot of global variables so I could use them all around my code.
global what_is_answer_entry
what_is_answer_entry = Entry(root4)
what_is_answer_entry.pack()
I then used the get() function to retrieve what the user typed.
global what_is_answer_entry_get
what_is_answer_entry_get = what_is_answer_entry.get()
This is the exact process I did for both ask_an_entry_get and what_is_answer_entry_get. However for some reason only ask_an_entry_get is printed, while what_is_answer_entry_get is printing nothing in the console.
from tkinter import *
root = Tk()
root.geometry("500x500")
txt1 = StringVar()
txt2 = StringVar()
def txt_printer():
print(txt1.get())
print(txt2.get())
x = Entry(root, textvariable=txt1, width=20)
x.place(x=0, y=0)
y = Entry(root, textvariable=txt2, width=20)
y.place(x=0, y=50)
btn_print = Button(root, text="print", command=txt_printer)
btn_print.place(x=0, y=100)
# Or if you want to show the txt on window then:
def txt_on_window():
lb1 = Label(root, text=txt1.get())
lb1.place(x=0, y=200)
lb2 = Label(root, text=txt2.get())
lb2.place(x=0, y=235)
btn_print_on_window = Button(root, text="print on screen", command=txt_on_window)
btn_print_on_window.place(x=0, y=150)
root.mainloop()

Tkinter - Iterating default text entry

I'm trying to create a GUI which will enable me to create folders with iterating names each time I click a button, i.e. 'folder_1', 'folder_2, 'folder_3',... which is isn't too difficult.
But, I also want the ability to manually change the number at which the iteration starts: I can enter '10' in an entry box and click the button, which would create 'folder_10' and each time I click the button after that it would continue to iterate, i.e folder_11, folder_12, folder_13,...
It would also be very helpful if the entry box contained the number of the next folder, as a default (that I can change manually), to be created when I click the button.
I've been trying to get something like this to work but no luck:
from tkinter import *
master = Tk()
master.counter = 0
def create_folder():
newfoldername = 'Folder_'+e1.get()+'/'
master.counter += 1
print(newfoldername)
#...folder creation here (I know how to do this...)
e1 = Entry(master)
e1.insert(0, master.counter)
e1.grid(row=0, column=1)
Button(master, text='Create folder', command=create_folder).grid(row=1,
column=1)
mainloop()
I am newbie to python so this might be really simple...
Thanks.
I would recommend you use IntVar()(If you type string in the Entry and use .get(),you will get error.) or StringVar().
from tkinter import *
master = Tk()
master.counter = IntVar()
master.counter.set(0)
def create_folder():
newfoldername = 'Folder_'+str(master.counter.get())+'/'
master.counter.set(master.counter.get()+1)
print(newfoldername)
#...folder creation here (I know how to do this...)
e1 = Entry(master, textvariable=master.counter)
e1.grid(row=0, column=1)
Button(master, text='Create folder', command=create_folder).grid(row=1,
column=1)
mainloop()
Shows the next value in the Entry box and creates directory with that number. If you change the value in the Entry box, it continues from there.
from tkinter import *
master = Tk()
master.counter = 0
def create_folder():
newfoldername = 'Folder_'+e1.get()+'/'
master.counter = int(e1.get())
master.counter += 1
e1.delete(0, END)
e1.insert(0, str(master.counter))
print(newfoldername)
#...folder creation here (I know how to do this...)
e1 = Entry(master)
e1.insert(0, master.counter)
e1.grid(row=0, column=1)
Button(master, text='Create folder', command=create_folder).grid(row=1,
column=1)
mainloop()

Python/Tkinter - clear the graphical interface screen

i am developing an application to calculate some taxes and show the result in the graphical interface. The code itself works perfectly, but if i use numbers with bigger squares, the result overlaps over the previous one. My question is, is it possible to clear the previous result and calculate the new one?
Follow the complete code below:
from tkinter import *
root = Tk()
l_vlrRec = Label(root, text='Receita')
l_vlrRec.place(x=10, y=10)
e_vlrRec = Entry(root)
e_vlrRec.place(x=75, y=10, width=75)
def calcular():
receita = float(e_vlrRec.get())
l_result = Label(root, text='{:.2f}'.format(receita))
l_result.place(x=10, y=150)
e_vlrRec.delete(0, END)
bt = Button(root, text='Calcular', command=calcular)
bt.place(x=10, y=50)
root.mainloop()
You can use the label's textvariable and also you don't have to instantiate a new Label every time the button is pressed:
v_result = DoubleVar()
l_result = Label(root, textvariable=v_result)
l_result.place(x=10, y=150)
def calcular():
v_result.set(round(float(e_vlrRec.get()),2))
You can do the same for your Entry object e_vlrRec so you don't have to cast the string you get by calling e_vlrRec.get() but use the variable's get() instead
Without using textvariable you can also reconfigure the label's text parameter:
l_result.configure(text='{:.2f}'.format(receita))
or
l_result['text'] = '{:.2f}'.format(receita)

Making text appear in Gui instead of python shell

I'm making a GUI with python and tkinter That prompts user the Mac Address of his pc and asks for a code The Python snippet i have used for retrieving the MAc address is :
import uuid
def get_mac():
mac_num = hex(uuid.getnode()).replace('0x', '').upper()
mac = ''.join(mac_num[i : i + 2] for i in range(0, 11, 2))
return mac
x= get_mac()
print x
I have also made a gui containing the two fields as shown below
However when i execute the python snippet the mac address is displayed outside the python gui and in the python shell, how can i make the mac address appear in the space provided in the GUi itself
Here is the code for the gui:
from Tkinter import *
from ttk import *
root =Tk()
def show_form():
bottomFrame = Frame(root)
bottomFrame.pack(side=BOTTOM)
b = Button(bottomFrame,text="ACTIVATE",command=lambda: show_call_back(root))
b1 = Button(bottomFrame, text="TRIM")
b2 = Button(bottomFrame, text="OVERLAY")
b3 = Button(bottomFrame, text="MERGE")
b.pack(side=RIGHT,padx=8,pady=26)
b1.pack(side=LEFT, padx=8, pady=26)
b1.config(state='disabled')
b2.pack(side=LEFT, padx=8, pady=26)
b2.config(state='disabled')
b3.pack(side=LEFT, padx=8, pady=26)
b3.config(state='disabled')
root.mainloop()
def show_call_back(parent):
top = Toplevel(parent)
top.geometry("250x200+600+250")
top.resizable(width=False, height=False)
top.title("Activation")
Label(top, text="Mac Address:",).grid(row=0, sticky=W, padx=4)
Label(top, text="Code").grid(row=1, sticky=W, padx=4)
Entry(top).grid(row=1, column=1, sticky=E, pady=4)
Button(top, text="Submit", command=top.destroy).grid(row=2, column=1)
show_form()
root.mainloop()
After your last comment, the solution is quite simple: add a new Label to display the result of get_mac().
Solution - Add a Label in row=0 and text=get_mac().
hLbl = Label(top, text=get_mac(), bg='white', relief=SUNKEN, width = 15)
hLbl.grid(row=0, column=1, sticky=E, pady=4)
I have added bg='white' and relief=SUNKEN to a the same style as
an Entry. The extra width = 15 is to enlarge the size of the label.
Warning 1 - as #abccd comments, keep only one mainloop(), and place the root = Tk() after the function declaration.
Warning 2 - Instead of using root as a global variable in bottomFrame = Frame(root) of the function show_form(), add it as input parameter.
def show_form(my_root): # use my_root instead of global root
bottomFrame = Frame(my_root)
bottomFrame.pack(side=BOTTOM)
# also for the command parameter
b = Button(bottomFrame,text="ACTIVATE",command=lambda: show_call_back(my_root))
...
And call:
root = Tk()
show_form(root)
root.mainloop()
EDIT -------
Output - here is what I get under Python 3.5.0

Tkinter StringVar() only accepts the most recent input

I'm trying to make a small application that displays words from a list one-by-one. Below is my code:
from Tkinter import *
master = Tk()
master.title('Serial Position Effect')
myArray = ['book','chair','door']
def cycle(myArray, k):
t.set(myArray[k])
t = StringVar()
w = Label(master, height=3, width=15, font=('Helvetica', 118), textvariable = t)
for n in range(0,3):
cycle(myArray, n)
w.pack()
master.mainloop()
I was expecting the label to show book, chair, and door, but it only showed door on the window. I tried to modify the for loop like:
for n in range(0,3):
for x in range(0,10000):
cycle(myArray, n)
Because I thought the problem was that the program was cycling through the words too quickly. But with this modified code, the application, again, only showed door after a short delay. (The delay was probably because it was counting up to 10000.)
Finally I approached this a little differently - a little less efficient but I thought by coding it like this I would be able to identify the problem in my original code:
from Tkinter import *
master = Tk()
master.title('Serial Position Effect')
#myArray = ['book','chair','door']
#def cycle(myArray, k):
# t.set(myArray[k])
t = StringVar()
w = Label(master, height=3, width=15, font=('Helvetica', 118), textvariable = t)
for n in range(0,10000)
t.set('book')
for n in range(0,10000)
t.set('chair')
for n in range(0,10000)
t.set('door')
w.pack()
master.mainloop()
Again, the window only displayed door.
I'm new to GUI programming with Python and Tkinter. I would really appreciate it if someone could help me out with this issue.
Thanks (=
The window won't even show up until you call mainloop, so calling set thousands of times won't have any visible effect, except for the very last call. You should use after to register callback functions that change the label some seconds in the future.
from Tkinter import *
master = Tk()
master.title('Serial Position Effect')
myArray = ['book','chair','door']
def cycle(myArray, k):
t.set(myArray[k])
t = StringVar()
w = Label(master, height=3, width=15, font=('Helvetica', 118), textvariable = t)
w.pack()
cycle(myArray,0)
master.after(1000, lambda: cycle(myArray, 1))
master.after(2000, lambda: cycle(myArray, 2))
master.mainloop()
You can also have the after-registered function call after itself, if you want the words to cycle forever.
from Tkinter import *
master = Tk()
master.title('Serial Position Effect')
myArray = ['book','chair','door']
cur_idx = -1
def cycle():
global cur_idx
cur_idx = (cur_idx + 1) % len(myArray)
t.set(myArray[cur_idx])
master.after(1000, cycle)
t = StringVar()
w = Label(master, height=3, width=15, font=('Helvetica', 118), textvariable = t)
w.pack()
cycle()
master.mainloop()

Categories

Resources