Python Tk _tkinter.TclError: invalid command name ".42818376" - python

I am getting the error mentioned in the title of the post I really just want this to work. Been working on this problem for a while now and it is frustrating. My ultimate goal is to obtain the values for the varables text, chkvar, and v.
Thanks to anyone who can reply and help on this!!
#!C:/Python27/python.exe
from Tkinter import *
import ImageTk, Image
root = Tk()
root.title('HADOUKEN!')
def killwindow():
root.destroy()
text = Text(root, height=16, width=40)
scroll = Scrollbar(root, command=text.yview)
text.configure(yscrollcommand=scroll.set)
text.grid(sticky=E)
scroll.grid(row=0,column=1,sticky='ns')
text.focus()
chkvar = IntVar()
chkvar.set(0)
c = Checkbutton(root, text="CaseIt", variable=chkvar)
c.grid(row=1,column=0,sticky=W)
v = ""
radio1 = Radiobutton(root, text="Src", variable=v, value=1)
radio1.grid(row=1,column=0)
radio1.focus()
radio2 = Radiobutton(root, text="Dst", variable=v, value=2)
radio2.grid(row=2,column=0)
b1 = Button(root, text="Submit", command=killwindow)
b1.grid(row=1, column=2)
img = ImageTk.PhotoImage(Image.open("Hadoken.gif"))
panel = Label(root, image = img)
panel.grid(row=0, column=2)
root.mainloop()
tk1 = text.get(text)
tk2 = chkvar.get(chkvar)
tk3 = v.get(v)
print tk1
print tk2
print tk3

Once mainloop exits, the widgets no longer exist. When you do text.get(text), you're trying to access a deleted widget. Tkinter simply isn't designed to allow you to access widgets after the main window has been destroyed.
The quick solution is to modify killwindow to get the values before it destroys the window, and store them in a global variable which you can access after mainloop exits.

The program didn't make it through the variable getting, so it never reported the incorrect method calls. I made a few changes to the original code (added a textval StringVar, and changed the v variable to another IntVar). I had a feeling the "associated variables" wouldn't have a problem, and didn't need to be included in the killwindow code. The only variable I grab in killwindow is the text data.
Working code (changed lines marked with #++) :
#!C:/Python27/python.exe
from Tkinter import *
import ImageTk, Image
root = Tk()
root.title('HADOUKEN!')
textval = StringVar() #++ added
def killwindow():
textval.set(text.get('1.0',END)) #++ grab contents before destruction
root.destroy()
text = Text(root, height=16, width=40)
scroll = Scrollbar(root, command=text.yview)
text.configure(yscrollcommand=scroll.set)
text.grid(sticky=E)
scroll.grid(row=0,column=1,sticky='ns')
text.focus()
chkvar = IntVar()
chkvar.set(0)
c = Checkbutton(root, text="CaseIt", variable=chkvar)
c.grid(row=1,column=0,sticky=W)
v = IntVar() #++ changed
v.set(1) #++ initial value
radio1 = Radiobutton(root, text="Src", variable=v, value=1)
radio1.grid(row=1,column=0)
radio1.focus()
radio2 = Radiobutton(root, text="Dst", variable=v, value=2)
radio2.grid(row=2,column=0)
b1 = Button(root, text="Submit", command=killwindow)
b1.grid(row=1, column=2)
img = ImageTk.PhotoImage(Image.open("Hadoken.gif"))
panel = Label(root, image = img)
panel.grid(row=0, column=2)
root.mainloop()
# windows are destroyed at this point
tk1 = textval.get() #++ changed
tk2 = chkvar.get() #++ changed
tk3 = v.get() #++ changed
print tk1
print tk2
print tk3

Related

retrieve selected value from a binded combobox in tkinter

I am trying to retrieve the selected value from a binded combobox.
In the below code, I have binded the combobox named “LSF_Combo” to another combobox “Queue _Combo” . I am trying to retrieve the selected value from the “Queue_Combo”, using Queue_Combo.get() method, but I am not able to do so, since its scope is limited within LSF_fields_Enable(event) inner function. I am able to retrieve the selected value of LSF_Combo using LSF_Combo.get() method.
Please let me know if anyone has suggestions for retrieving the selected value from the “Queue_Combo” combobox and furhter nested comboboxes "MT_Combo: and "Merge_Combo", so that I should be able to access and assign these to a variable outside the "LSF_Fields_Enable" function scope.
For example, If i had selected 'priority' from "Queue_Combo" and had selected "MT" from "MT_Combo", i should be able to assign these strings to variables outisde LSF_Fields_Enable(event) function. From the 'def run_program()' variable 'b' should have sting equals to 'priority' (since i have selected this) and variable 'c' should have string equals to 'MT'.
from tkinter import *
import tkinter as tk
from tkinter import ttk
root = Tk()
root.geometry("800x450")
def Gui_main():
Queue_Combo_list = ['normal', 'priority', 'devices', 'grid']
Queue_Combo = ttk.Combobox(root, values=Queue_Combo_list, width=10, state="readonly")
Merge_Combo_list = ['LST_SET_ML', 'LST_SET_EQU']
Merge_Combo = ttk.Combobox(root, values=Merge_Combo_list, width=12)
MT_Combo_list = ['MT', 'MTFLEX']
MT_Combo = ttk.Combobox(root, values=MT_Combo_list, width=10)
def LSF_Fields_Enable(event):
# global Queue_Combo, VCO_Combo, OS_Combo
VCO_1 = None
if LSF_Combo.get() == 'LSF':
# # section for Queue Type
Queue_Combo_label = tk.Label(root, text="Queue: ").grid(row=2, column=1, padx=5,sticky=W)
Queue_Combo.set("normal")
Queue_Combo.grid(row=2, column=1, padx=55, pady=5, sticky=W)
def MT_MT_flex(choice):
def Manage_run_mode(choice):
# if Merge_Combo.get() == 'LSF_SET_EQU' or 'LSF_SET_MAN':
if Merge_Combo.get() != 'LSF_SET_ML':
label = tk.Label(root, text="CPU No:").grid(row=4, column=3, padx=10,sticky=tk.W)
CPU_radio_button = tk.IntVar()
R1 = Radiobutton(root, text="2", variable=CPU_radio_button, value=1).place(x=50, y=520)
if MT_Combo.get() == 'MT':
# # section for choosing a file version
Merge_Combo_label = tk.Label(root, text="Merge: ").grid(row=6, column=2, padx=10,sticky=W)
Merge_Combo.set("LST_SET_ML")
Merge_Combo.grid(row=6, column=2, padx=65, pady=15, sticky=tk.E)
Merge_Combo.bind('<<ComboboxSelected>>',Manage_run_mode)
MT_Combo_label = tk.Label(root, text="MT/MTflex: ").grid(row=2, column=3, padx=10,sticky=W)
MT_Combo.set("MT")
MT_Combo.grid(row=2, column=4, padx=5, pady=5, sticky=tk.E)
MT_Combo.bind('<<ComboboxSelected>>',MT_MT_flex)
# LSF_Fields_Enable()
LSF_Combo_label = tk.Label(root, text="Fill: ").grid(row=2, column=0, sticky=W)
LSF_Combo_list = ['LSF', 'LOCAL']
LSF_Combo = ttk.Combobox(root, values=LSF_Combo_list, width=10, state="readonly", background='white')
LSF_Combo.set('LSF')
LSF_Combo.grid(row=2, column=0, padx=25, pady=5, sticky=W)
LSF_Combo.bind('<<ComboboxSelected>>', LSF_Fields_Enable)
Queue_Combo.bind('<<ComboboxSelected>>', lambda _: print(Queue_Combo.get()))
MT_Combo.bind('<<ComboboxSelected>>', lambda _: print(MT_Combo.get()))
Merge_Combo.bind('<<ComboboxSelected>>', lambda _: print(Merge_Combo.get()))
# a = LSF_Combo.bind("<Return", LSF_Fields_Enable)
def run_program():
a = LSF_Combo.get()
print(a)
b = Queue_Combo.get()
print(b)
c = MT_Combo.get()
d = Merge_Combo.get()
close = Button(root, text ='close', command= root.destroy).grid(row=10, column=2, pady=60, sticky=E)
check_combo_get =Button (root, text ='check_combo_get', command = run_program).grid(row=10, column=1, padx=15,pady=60, sticky=E)
root.mainloop()
if __name__ == "__main__":
Gui_main()
There is not an easy way to fix this problem in your setup.
But the solution is easy, if you just go ahead and restructure your code a little:
Define the combobox outside the LSF_Fields_Enable function and also asign its values at startup.
Queue_Combo_list = ['normal', 'priority', 'devices', 'grid']
Queue_Combo = ttk.Combobox(root, values=Queue_Combo_list, width=10, state="readonly")
Now bind the ComboboxSelected Event to whatever function you want to have (in this example a simple print).
Queue_Combo.bind('<<ComboboxSelected>>', lambda _: print(Queue_Combo.get()))
And there you go!
Now the print function is executed every time the selection changes for the queue-combobox.
Hope this helps :)
EDIT:
In the updated Code below I reformated your code to make it more readable and to achieve what you wanted to have.
The Value of the ComboBoxes are now assigned to variables ("Queue_Combo_variable", "LSF_Combo_variable").
You can access their values using:
Queue_Combo_variable.get()
I tried my best to comment the entire to be as understandable as possible. Let me now if this is how you imagined it to be!
NEW CODE:
from tkinter import ttk, Tk, Label, Button, StringVar
from tkinter.constants import W, E
def Gui_main():
# Create tkinter (window) instance
root = Tk()
root.geometry("300x250")
# Define LSF_Combox (Combobox)
LSF_Combo_variable = StringVar()
LSF_Combo_label = Label(root, text="Fill: ") # Label
LSF_Combo_label.grid(row=2, column=0, sticky=W)
LSF_Combo_list = ['LSF', 'LOCAL']
LSF_Combo = ttk.Combobox(root, values=LSF_Combo_list, textvariable=LSF_Combo_variable, width=10, state="readonly", background='white')
LSF_Combo.set('LSF')
LSF_Combo.grid(row=2, column=0, padx=25, pady=5, sticky=W) # and place it on the screen
# Define Queue_Combo (Combobox)
Queue_Combo_variable = StringVar()
Queue_Combo_label = Label(root, text="Queue: ") # Label
Queue_Combo_list = ['normal', 'priority', 'devices', 'grid']
Queue_Combo = ttk.Combobox(root, values=Queue_Combo_list, textvariable=Queue_Combo_variable, width=10, state="readonly")
# ==> The Queue_Combo_variable now always stores the value which is currently selected in the queue_combo (box)
#################################################################################################################################
#### ==> Through the following code the specfied function (LSF_Combo_changed) is always called, once the variable value changes #
#################################################################################################################################
LSF_Combo_variable.trace_add("write", lambda _0, _1, _2: LSF_Combo_changed())
Queue_Combo_variable.trace_add("write", lambda _0, _1, _2: print(Queue_Combo_variable.get()))
# If you don't understand, what all of this does, it doesn't matter just now, that you can change the print function to be the function you want to call instead!
# This function is now executed every time when the LSF_Combo (box) is changed (=> "Something has been selected in the left combobox")
def LSF_Combo_changed():
# If "LSF" has been selected, show the Queue_Combo Box
if LSF_Combo.get() == 'LSF':
Queue_Combo.set("normal")
Queue_Combo.grid(row=2, column=1, padx=55, pady=5, sticky=W)
Queue_Combo_label.grid(row=2, column=1, padx=10,sticky=W)
return Queue_Combo.get()
else: # If that hasn't been selected, "forget" the position of the Queue_Combo Box & Label ("Hide them")
Queue_Combo.grid_forget()
Queue_Combo_label.grid_forget()
return None
# Close Button
close_button = Button(root, text ='close', command= root.destroy)
close_button.grid(row=10, pady=60, sticky=E)
# Show window (tkinter instance)
root.mainloop()
if __name__ == "__main__":
Gui_main()

How to select only one Radiobutton in tkinter

I have two radiobutton in my GUI but i want to able select only one at a time with the code below am able to select both radiobutton . I tried the checkbutton which also i can select both options.
from tkinter import *
def content():
if not option1.get() and not option2.get():
print("not allowed, select one dude")
else:
print("welcome dude")
option1.set(False)
option2.set(False)
root = Tk()
root.geometry("400x400")
option1 = BooleanVar(value=False)
R1 = Radiobutton(root, text="MALE", value=1, var=option1)
R1.pack()
option2 = BooleanVar(value=False)
R2 = Radiobutton(root, text="FEMALE", value=2, var=option2)
R2.pack()
b = Button(root, text="print", command=content)
b.pack(side="bottom")
root.mainloop()
You must bind both radiobuttons to the same variable.
Besides, the variable will receive the value specified in the value keyword argument.
I suggest you do the following:
option = StringVar()
R1 = Radiobutton(root, text="MALE", value="male", var=option)
R2 = Radiobutton(root, text="FEMALE", value="female", var=option)
You can know what item is currently selected, by tracing the option variable, and by calling its get method.
For instance, the following will print either "male" or "female" whenever the corresponding radiobutton is checked.
def print_var(*_):
print(option.get())
root = Tk()
root.geometry("400x400")
option = StringVar()
R1 = Radiobutton(root, text="MALE", value="male", var=option)
R2 = Radiobutton(root, text="FEMALE", value="female", var=option)
R1.pack()
R2.pack()
option.trace('w', print_var)
root.mainloop()
A more complete example, according to your demand.
This script will display a window with two radiobuttons and a button.
When the button is clicked, a message is printed that depends upon whether an option was selected or not.
from tkinter import *
def validate():
value = option.get()
if value == "male":
print("Welcome dude")
elif value == "female":
print("Welcome gurl")
else:
print("An option must be selected")
root = Tk()
root.geometry("400x400")
option = StringVar()
R1 = Radiobutton(root, text="MALE", value="male", var=option)
R2 = Radiobutton(root, text="FEMALE", value="female", var=option)
button = Button(root, text="OK", command=validate)
R1.pack()
R2.pack()
button.pack()
root.mainloop()
As a side note, you should never import a module with a star, eg from tkinter import *.
In short, it pollutes the namespace. More on this post.
I presume you are wanting to create one radio button with multiple values which only allows one selection? You would be better to populate an array and run a loop to fill the radio button. Perhaps something like this?
from tkinter import *
root = Tk()
root.geometry("400x400")
GENDERS = [
("Male", "M"),
("Female", "F"),
("Other", "O")
]
v = StringVar()
v.set("L") # initialize
for text, gender in GENDERS:
b = Radiobutton(root, text=text,
variable=v, value=gender)
b.pack(anchor=W)
root.mainloop()
The easiest way to do it that i found is this -
you have to give them both the same variable so that compiler can know that the user can only choose one...
from tkinter import *
window = Tk()
window.geometry("100x100")
var = IntVar()
radio = Radiobutton(window, text="this", variable=var, value=1)
radio.pack()
radio2 = Radiobutton(window, text="or this", variable=var, value=2)
radio2.pack()
window.mainloop()

Making a Tkinter Listbox with Scrolll

I'm currently trying to make a Listbox with a Scroll bar on the side appear on my Tkinter Window. I can't figure out how to make the Scrollbar size the same size as my listbox. Heres my code:
global R3
global lb
R3 = Tk()
gg = "white"
g = "blue"
R3.geometry('720x720')
R3.title(username + " Dropbox")
R3.resizable(width=False, height=False)
logoutbt = Button(R3, text="Logout", width=10, height=2, bg=g, fg=gg, font="5", relief=RAISED, overrelief=RIDGE, command=rectologout)
upload = Button(R3, text="Upload", width=10, height=2, bg=g, fg=gg, font="5", relief=RAISED, overrelief=RIDGE, command=rectoupload)
logoutbt.place(x=220, y=500)
upload.place(x=480, y=500)
button1 = Button(R3, text='Receive file', width=10, height=2, bg=g, fg=gg, font="5", relief=RAISED, overrelief=RIDGE,command = get_file)
lb = Listbox(R3, height=6,width = 15)
s.send("RETREIVEA-"+username)
file_list = s.recv(1024).split("-")
if file_list == [""]:
button1.config(state = DISABLED)
for file in file_list:
lb.insert("end", file)
yscroll = Scrollbar(R3, orient=VERTICAL)
lb['yscrollcommand'] = yscroll.set
yscroll['command'] = lb.yview
lb.place(x=280,y=200)
yscroll.place(x=370,y=200)
button1.place(x=400, y=200)
R3.mainloop()
Any suggestions on how to do it?
First of all, please read how to create a Minimal, Complete and Verifiable example.
Your code lacks imports and references non-initialized objects / variables / functions.
How to achieve what you want?
Either use grid instead of place or pass height parameters to lb.place(..., height=<whatever you want>) and yscroll.place(..., height=<whatever you want>)

I need a to send data to script with submit button

I'm building a python GUI and there I got 2 text boxes.
I want to create a submit button that will take the data from those 2 text boxes and send them to start(save_place, website_url) function.
This is what I got so far:
from Tkinter import *
def start(save_place, website_url):
#something
app = Tk()
top_app = Frame(app)
top_app.pack()
save_location = Entry(top_app, width=20)
url = Entry(top_app, width=20)
save_location.grid(sticky=W, row=0)
url.grid(sticky=W, row=1)
save_place = save_location.get("1.0", END)
website_url = url.get("1.0", END)
button_start = Button(top_app, text="Start", fg="green", command=start(save_place,website_url))
button_start.grid(sticky=W, row=2, pady=20)
app.mainloop()
I also tried this:
from Tkinter import *
def start():
save_place = save_loc.get()
website_url = urls.get()
print (save_place + " " + website_url)
app = Tk()
top_app = Frame(app)
top_app.pack()
save_loc = StringVar()
save_location = Entry(top_app, textvariable=save_loc, width=85)
urls = StringVar()
url = Entry(top_app, textvariable=urls, width=85)
button_start = Button(top_app, text="Start", fg="green", command=start)
button_start.grid(sticky=W, row=2, pady=20)
app.mainloop()
And it didn't work.
How can I make this script send the inputs in the text boxes to the function?
Thanks to all the helpers :)
As mentioned in the previous response "about how to call a function", you just put command = start and put save_place = save_location.get()
in start function, however you can use save_location = Entry(top_app, width=20), so the total prg:
from Tkinter import *
def start():
#something
save_place = save_location.get()
website_url = url.get()
print save_place,website_url
app = Tk()
top_app = Frame(app)
top_app.pack()
save_location = Entry(top_app, width=20)
url = Entry(top_app, width=20)
save_location.grid(sticky=W, row=0)
url.grid(sticky=W, row=1)
button_start = Button(top_app, text="Start", fg="green", command=start)
button_start.grid(sticky=W, row=2, pady=20)
app.mainloop()
command=start(save_place,website_url) doesn't do what you think its doing. It's assigning the result of the function call to the command. (Which is probably None). Bind your Entry boxes to StringVar like:
location = StringVar()
Entry(top_app, textvariable=location, width=20)
Then you assign the function call to the command parameter using command = start. Inside the function you can access the value in the Entry using location.get(). To set the value use the corresponding method location.set(value)

Pass values to python script with Tkinter

So I've written a python script that uses the PIL library to format a png passed to it. I want to make the script more user friendly and after looking around I saw the Tkinter library which seemed perfect. Basically the script has five variables that I need to pass to it for it to run. I'm currently using the raw_input() function to asking the user for the following variables:
path_to_png
title
subtitle
source
sample_size
Once received the script runs and exports the formatted png. I've used Tkinter to build those basic inputs as you can see from the picture below but I don't know how to pass the inputed text values and the file path from the choose png button to their respective variables.
from Tkinter import *
from tkFileDialog import askopenfilename
from tkMessageBox import *
app = Tk()
app.title("Picture Formatting")
app.geometry('500x350+200+200')
#
def callback():
chart_path = askopenfilename()
return
def title_data():
title_data = chart_title
return
errmsg = 'Error!'
browse_botton = Button(app, text="Choose png", width=15, command=callback)
browse_botton.pack(side='top', padx=15, pady=15)
# Get chart data
chart_title = StringVar()
title = Entry(app, textvariable = chart_title)
title.pack(padx=15, pady=15)
chart_subtitle = StringVar()
subtitle = Entry(app, textvariable = chart_subtitle)
subtitle.pack(padx=15, pady=15)
chart_source = StringVar()
source = Entry(app, textvariable = chart_source)
source.pack(padx=15, pady=15)
chart_sample_size = IntVar()
sample_size = Entry(app, textvariable = chart_sample_size)
sample_size.pack(padx=15, pady=15)
submit_button = Button(app, text="Submit", width=15)
submit_button.pack(side='bottom', padx=15, pady=15)
app.mainloop()
I have tried your code, and I added some lines:
from Tkinter import *
from tkFileDialog import askopenfilename
from tkMessageBox import *
app = Tk()
app.title("Picture Formatting")
app.geometry('500x350+200+200')
#
def callback():
global chart_path
chart_path = askopenfilename()
return
def title_data():
title_data = chart_title
return
def calculate():
chart_title = title.get()
chart_subtitle = subtitle.get()
chart_source = source.get()
chart_sample_size = sample_size.get()
print "chart_path : ", chart_path
print "chart_title : ", chart_title
print "chart_subtitle : ", chart_subtitle
print "chart_source : ", chart_source
print "chart_sample_size : ", chart_sample_size
#Call your functions here
return
errmsg = 'Error!'
# Get chart data
chart_path = ''
browse_botton = Button(app, text="Choose png", width=15, command=callback)
browse_botton.pack(side='top', padx=15, pady=15)
chart_title = StringVar()
title = Entry(app, textvariable = chart_title)
title.pack(padx=15, pady=15)
chart_subtitle = StringVar()
subtitle = Entry(app, textvariable = chart_subtitle)
subtitle.pack(padx=15, pady=15)
chart_source = StringVar()
source = Entry(app, textvariable = chart_source)
source.pack(padx=15, pady=15)
chart_sample_size = IntVar()
sample_size = Entry(app, textvariable = chart_sample_size)
sample_size.pack(padx=15, pady=15)
submit_button = Button(app, text="Submit", width=15, command=calculate)
submit_button.pack(side='bottom', padx=15, pady=15)
app.mainloop()
I think the problem you want to ask is how to get the text values in the entry widgets and get the path text from the askopenfilename() function. You can use the method Entry.get() to get the text value in certain entry widget.
And you can just use str = askopenfilename() to get the path's text value. But because this line of code is written in a function, you need to declare that it is a global variable or create a class to contain them, or the interpreter will consider that variable is an local variable and it will not be passed to the function calculate() which I added.
Since you didn't use a class to contain the variables, I also use the variables as global variables. It is not a good design. You can consider to create a class instead.
In order to receive the value from an entry widget, you would want to use the get() function. The get() function will return whatever is in the entry widget. For instance in your case: response = sample_size.get() will set the variable response to 0. See this page for more documentation on the entry widget.
Hope this helped.

Categories