I am new to programming and I have been trying to understand when python/tkinter refresh values of dictionaries.
I've got the following code which basically creates a dictionary called states in which the item is linked to a value of 0.
I then launch the GUI.
from Tkinter import *
import Tkinter, tkFileDialog
states = {'open_thermo':0}
def is_true(state): # in quotes
states[state] = 1
def Station():
Station = Tk()
if states['open_thermo'] == True:
Label(master=Station, text='Thermo has been opened').grid(row=0)
Button(master=Station, text='press to end', command= lambda: combine_funcs(Station.destroy())).grid(row=4, columnspan=1, column=1, pady=4)
else:
Label(master=Station, text='Do you wish to open Thermo ?').grid(row=0)
Button(master=Station, text='press to open Thermo', command= lambda: is_true('open_thermo')).grid(row=4, columnspan=1, column=1, pady=4)
print states['open_thermo'] == True #1st print statement
mainloop()
start = Tk()
Label(master=start, text='start').grid(row=0)
Button(master=start, text='press to start', command= lambda: combine_funcs(start.destroy(),Station())).grid(row=4, columnspan=1, column=1, pady=4)
mainloop()
print states['open_thermo'] == True #2nd print statement
I do not understand two things:
why the print statement commented as #1st print statement doesn't
print over and over again before I click the button. I though
mainloop() repeated the code above it over and over again.
why, when I click the button, the value of states['open_thermo']
doesn't change to 1, and then the if states['open_thermo'] == True: statement becomes true because of mainloop(). I would expect
the label to change to:
Label(master=Station, text='Thermo has been opened').grid(row=0)
Button(master=Station, text='press to end', command= lambda: combine_funcs(Station.destroy())).grid(row=4, columnspan=1, column=1, pady=4)
Thank you in advance for your help !
I am new to programming and I have been trying to understand when python/tkinter refresh values of dictionaries.
python/tkinter never "refreshes values of dictionaries". The dictionaries change immediately when you tell them to change.
why the print statement commented as #1st print statement doesn't print over and over again before I click the button. I though mainloop() repeated the code above it over and over again.
No, mainloop does not repeat code that is above it. The code above it runs exactly once. mainloop() is a simple loop that waits for events and responds to them based on bindings. No code will run after mainloop until the window is destroyed.
why, when I click the button, the value of states['open_thermo'] doesn't change to 1, and then the if states['open_thermo'] == True: statement becomes true because of mainloop().
It's unclear which button you're talking about. However, it looks like both buttons that call is_true will actually change the value. I don't see any evidence that it doesn't. Since is_true doesn't do anything except change the value, I don't see how you think it's not changing.
Again, the code in Station runs exactly once when it is called. It doesn't run over and over and over. You click the button once, it is called once.
Related
I know there are better ways about this, but I cant figure out what's
wrong about this code, or at least, why it wont function the way I want it. Currently I made a simple test program to try my concept away from my
main code.
from tkinter import *
root = Tk()
test = True
def click():
global test
print("working")
test = False
button = Button(root, text="Hi", command=click)
if test:
button.pack()
root.mainloop()
Everything runs fine but when I press the button all I get is the message "working" without the button going away.
In your code python checks if test is True and as it is, it packs the button and moves on. What you need to use is <tkinter widget>.pack_forget(). It removes the widget from the screen without destroying it. If you later call pack it should put it back in its original place. This is your code with the pack_forget:
from tkinter import *
root = Tk()
def click():
print("working")
button.pack_forget()
button = Button(root, text="Hi", command=click)
button.pack()
root.mainloop()
(Long Question)
I'm trying to write a piece of code that will take a file path from the user using a tkinter textbox when a button is pressed. It would then convert that textbox entry to a string attached to a normal python variable so I can use that variable in a function later to use that file. The code I attached can make the label copy the text box entry, but I cannot use that variable or myvar in "normal python code". Also, in the code I tried returning myvar.get() through the function mywarWritten, but I cant set a variable equal to the mywarWritten(parameters) because that is dependent on the textbox entry that doesn't happen until the button is pressed. When the button is pressed the print function works printing the statement but it doesn't return please when the function is set equal to attempt.
(In Short)
I want to take a value, or string, from the user using a Tkinter text box, and use the entry as a normal python variable. Preferably the value in the text box would only be taken when a button is pressed.
from Tkinter import *
import Tkinter as tk
root = Tk()
root.title("MyApp")
myvar = StringVar()
def mywarWritten(*args):
print "mywarWritten",myvar.get()
please = myvar.get()
return please
#trying to make the function return the textbox entry but fails
attempt = mywarWritten()
print "plz %s" % (attempt)
#trying to just set it equal too but also fails
python_variable = myvar.get()
label = Label(root, textvariable=myvar)
label.pack()
text_entry = tk.Entry(root, textvariable=myvar)
button1 = tk.Button(root, text="Back to Home", command=lambda: mywarWritten())
button1.pack()
text_entry.pack()
#trying attempt and pythonvariable in "normal python code"
print attempt
print pythonvariable
root.mainloop()
Thanks for the help in advance.
You seem to have a few misunderstandings about scope, imports, references, and functions. myvar is already accessible, and all you have to do to access it is get() it. Don't import the same module multiple times, and try to avoid from x import *. Returning a value to a button doesn't make any sense and has no effect. Every line of code not in a function or class is executed immediately, so attempt = mywarWritten() and all of the other several times you did that outside a function will get the value of that StringVar as soon as the program runs, before there's anything in it. And lambda: func() is just func.
import Tkinter as tk
root = tk.Tk()
root.title("MyApp")
myvar = tk.StringVar()
def mywarWritten(*args):
print "mywarWritten", myvar.get()
label = tk.Label(root, textvariable=myvar)
label.pack()
text_entry = tk.Entry(root, textvariable=myvar)
button1 = tk.Button(root, text="Back to Home", command=mywarWritten)
button1.pack()
text_entry.pack()
root.mainloop()
Any time you want to access the contents of that entry widget, just do myvar.get() and there it will be.
You also have mywarWritten instead of my_var_written, with a v for var.
Overall, I very highly recommend you read the official Python tutorial (and use Python 3, because it's better than Python 2).
I want to see continuously changing value of label in tkinter window. But I'm not seeing any of it unless I make a keyboard interrupt in MS-CMD while running which shows me the latest assigned value to label. Plz tell me ..What's going on & what's the correct code ??
import random
from Tkinter import *
def server() :
while True:
x= random.random()
print x
asensor.set(x)
app=Tk()
app.title("Server")
app.geometry('400x300+200+100')
b1=Button(app,text="Start Server",width=12,height=2,command=server)
b1.pack()
asensor=StringVar()
l=Label(app,textvariable=asensor,height=3)
l.pack()
app.mainloop()
The function server is called when you click the button, but that function contains an infinite loop. It just keep generating random numbers and sending these to asensor. You are probably not seeing any of it because the server function is run in the same thread as the GUI and it never gives the label a chance to update.
If you remove the while True bit from your code, a new number will be generate each time you click the button. Is that what you wanted to do?
Edit after comment by OP:
I see. In that case your code should be changed as follows:
import random
from Tkinter import Tk, Button, Label, StringVar
def server():
x = random.random()
print x
asensor.set(x)
def slowmotion():
server()
app.after(500, slowmotion)
app = Tk()
app.title("Server")
app.geometry('400x300+200+100')
b1 = Button(app, text="Start Server", width=12, height=2, command=slowmotion)
b1.pack()
asensor = StringVar()
asensor.set('initial value')
l = Label(app, textvariable=asensor, height=3)
l.pack()
app.mainloop()
I also introduced a new function, slowmotion, which does two things: 1) calls server, which updates displays the value, and 2) schedules itself to be executed again in 500ms. slowmotion is first ran when you first click the button.
The problem with your code was that it runs an infinite loop in the main GUI thread. This means once server is running, the GUI will not stop and will not get a chance to display the text you asked it to display.
I have been looking around for a long time for answers to this question but still hasn't find anything. I am creating a GUI using Tkinter, and I have two buttons that do mostly the same thing except they receive information from different widgets. One button is for an Entry widget and the other is for a Listbox widget.
The callback function for these two buttons is long (about 200 lines), so I don't want to have separate functions for each button. I have if-statements in the beginning of this callback function to check which button is clicked, and then the codes will take the corresponding value. But I am not sure if the following code shows the right way to do this because apparently it doesn't work perfectly in my program. The callback function would only work for the first time, and if I click the other button I will receive an error. Here is a sample code that I created to illustrate the idea. Note that I want to check if the button is clicked, I do not want to check if the 'value' exists. Please help.
from Tkinter import *
root = Tk()
def DoSomething():
# is this the right way to check which button is clicked?
if button1:
value = user_input.get()
elif button2:
value = choice.get(choice.curselection()[0])
# then more codes that take 'value' as input.
button1 = Button(master,text='Search',command=DoSomething)
button1.pack()
button2 = Button(master,text='Search',command=DoSomething)
button2.pack()
user_input = Entry(master)
user_input.pack()
choice = Listbox(master,selectmode=SINGLE)
choice.pack()
#assume there are items in the listbox, I skipped this portion
root.mainloop()
If you want to pass the actual widget into the callback, you can do it like this:
button1 = Button(master, text='Search')
button1.configure(command=lambda widget=button1: DoSomething(widget))
button2 = Button(master, text='Search')
button2.configure(command=lambda widget=button2: DoSomething(widget))
Another choice is to simply pass in a literal string if you don't really need a reference to the widget:
button1 = Button(..., command=lambda widget="button1": DoSomething(widget))
button2 = Button(..., command=lambda widget="button2": DoSomething(widget))
Another choice is to give each button a unique callback, and have that callback do only the thing that is unique to that button:
button1 = Button(..., command=ButtonOneCallback)
button2 = Button(..., command=ButtonTwoCallback)
def ButtonOneCallback():
value = user_input.get()
DoSomething(value)
def ButtonTwoCallback():
value=choice.get(choice.curselection()[0])
DoSomething(value)
def DoSomething(value):
...
There are other ways to solve the same problem, but hopefully this will give you the general idea of how to pass values to a button callback, or how you can avoid needing to do that in the first place.
I'm pretty new to Tkinter but starting to try to put more complex GUI's in my scripts. So this must be pretty basic but I can't figure out what's going wrong.
What I want is pretty simple, a bunch of data entry options and at the bottom an exit and submit buttons. It seems though that mainloop() or something else keeps running the button's command without any user input. Thus because of the exit button, the applet is destroyed before it even shows up. If I put the buttons outside of the mainloop(), there is no problem, but of course it doesn't make sense and the buttons don't show up.
button_exit = Tkinter.Button(root, text = 'Exit', command = root.destroy())
button_exit.grid(row=3, column=0, pady=10, sticky='E')
button_query = Tkinter.Button(root, text = 'Query', command = intQuery())
button_query.grid(row=3, column=1, padx=10, sticky='E')
root.mainloop()
That's basically the problem area of the code. The rest is just that data entry fields, most of the script hasn't even been written yet.
Thanks in advance.
Change
command = root.destroy()
to
command = root.destroy
The reason is this: The parentheses call the method, and method arguments are evaluated before being passed to the method. This is why your program is exiting too early.
Without the parentheses, you are referencing the method as an object which can be passed to the Tkinter.Button, stored, and called later when the button is pressed.
Then do the same with command = intQuery().