for bear in self.bears:
button=tk.Button(self,text=polar.spec(),command=lambda
id=polar.spec:self.polar_ad(id))
button.grid(row=_r,column=_c,sticky=W+E+N+S)
_row+=1
Hello, so i've created a number of buttons in a for loop, but when i click the button, i want to be able to disable it. If the buttons were created individually then i could use
button["state"]="disabled"
but how can i use this by using the id of the button? Thank you
I would add the buttons to an array upon creation, then loop through the array and check ids.
buttons = []
for bear in self.bears:
btn = tk.Button(self,text=polar.spec(),command=lambda id=polar.spec:self.polar_ad(id))
btn.grid(row=_r,column=_c,sticky=W+E+N+S)
buttons.append(btn)
_id += 1
_row += 1
Then check button IDs
for b in buttons:
if b.id == <id_of_button_press>:
b['state'] = "disabled"
I'm not sure if you can get a button's id this way, but the principal should make sense.
buttons=[]
num=0
for bear in self.bears:
button=tk.Button(self,text=polar.spec(),command=lambda
id=polar.spec,index=num:self.polar_ad(id,index))
button.grid(row=_r,column=_c,sticky=W+E+N+S)
num+=1
_row+=1
then
self.polar(id,index):
buttons[index]["state"]="disabled"
thank for your idea really helped me get on the right tracks #Uuuuuumm
Related
I'm making a study project, just a basic calendar, but I encountered an error, that I can't figure out. Firstly, I input the proper date, which later I append to a list. The next step is to click the button to list all events you already add, but I can't show it proper. It gets the awful brackets, that I can't get rid of. If I try the .format, unfortunately window shows only the first element of a list. Can you help me figure it out?
def window2():
print(events)
win2 = Toplevel(root)
win2.title("Lista wydarzeń")
win2.geometry("300x200")
events_label = Label(win2, text="Wydarzenia:")
events_label.pack()
if len(events) > 0:
for x in events:
events_show_label = Label(win2, text=events)
events_show_label.pack()
else:
no_events_label = Label(win2, text="Nie dodano żadnego wydarzenia.")
no_events_label.pack(pady=10)
I get the variables by .get() and add them to the list like that
events.append(f"Nazwa: {title} \nData: {date} {time}\n")
I want to add an event to a button such that whenever the button is clicked new text inputs are added row by row.
This might not be an optimal solution, but it works. You'll need to store the number of rows in a session state variable (https://docs.streamlit.io/library/api-reference/session-state). The variable "n_rows" is incremented everytime the add button is pressed, and we loop through "n_rows" number of times to create each row. Use st.experimental_rerun() to update the screen as soon as the button is pressed. Make sure to pass the index in loop as key.
if 'n_rows' not in st.session_state:
st.session_state.n_rows = 1
add = st.button(label="add")
if add:
st.session_state.n_rows += 1
st.experimental_rerun()
for i in range(st.session_state.n_rows):
#add text inputs here
st.text_input(label="Column Name", key=i) #Pass index as key
I'm trying add/remove an item (text of checkbox) to/from a list whenever a checkbox is checked/unchecked in tkinter.
My idea was to add a command to the checkbutton, like:
cb = Checkbutton(master,...,command=some_fun)
but I cannot think of a way to define the function. I was thinking the function should contain the widget attribute cget('text'), but the problem is I have many checkboxes made with the help of a loop.
I guess the question is: how can I reference the checkbox whose state got changed and is therefore calling the function some_fun?
The way I generated the checkboxes is:
cb_identities = []
for i in range(cb_max_num):
cb = Checkbutton(frame_data,bg="white")
cb_identities.append(cb)
And then I'm dynamically changing them depending on some radiobuttons:
def fun_chck(): #shows or hides checkbuttons based on radiobutton input
data = read_data(rb_var.get())
for i in range(cb_max_num):
cbname = (cb_identities[i])
if len(data)-1 < i:
cbname.grid_forget()
else:
cbname.config(text=data[i]) #I would place some_fun here, which gets text option of checked box
cbname.grid(row=i,column=1,sticky=W)
Update! I managed with the following code for anyone interested:
cb_var_init = [0] * cb_max_num #create the initial list of inactive checkbuttons, all 0
input_params=[] #list which needs to be populated/depopulated based on checkbutton state
def get_data(data): #populates a list with parameter from checked checkbuttons,
global cb_var_init
cb_var_list = list(map(lambda var: var.get(),list(cb_var.values())))
for i in range(len(data)):
if cb_var_list[i] > cb_var_init[i]:
input_params.append(data[i])
elif cb_var_list[i] < cb_var_init[i]:
input_params.remove(data[i])
cb_var_init = cb_var_list
return(input_params)
cb_var is a dictionary of IntVars, and data is a list of checkbuttons' names.
As for the command on each checkbutton, I used cbname.config(text=data[i],command=lambda: get_data(data)) as suggested in another topic for functions with arguments.
Now each time I check a checkbutton, I immediately get a list of parameters which should show in the next Frame, which is dynamically updated.
I have a function, which based on the count generates the comboboxes. I want to destroy any combobox which is available already whenever my count variable changes. I used winfo_exists to do this...but it throws an attribute error every time. Please help me with this.
Here is the code of that function:
def create(event):
count = combo.current()
print ("count")
print(count)
for i in range(1,count+2):
if (create_combo[i].winfo_exists()):
create_combo[i].destroy()
for i in range (1,count+2):
create = tk.StringVar()
create_combo[i]= ttk.Combobox(new_window_2,width = 15,textvariable = create, values = sheets)
#create_combo.set("Sheet " + str(i))
create_combo[i].grid(column = i, row =4, padx=10,pady=10)
To delete the widgets which are created in loop, can be deleted by using the method available in this link
Python Tkinter :removing widgets that were created using a for loop
This worked for me... I dont understand why winfo_exists didn't work.
Anyway Thanks!!
list_of_owner_widgets = []
def create(event):
count = combo.current()
print(count)
for widget in list_of_owner_widgets:
widget.destroy()
for i in range (1,count+2):
create = tk.StringVar()
create_combo[i]= ttk.Combobox(new_window_2,width = 15,textvariable = create, values = sheets)
list_of_owner_widgets.append(create_combo[i])
create_combo[i].grid(column = i, row =4, padx=10,pady=10)
If you wish to destroy a Python widget, be it a Checkbox in your case, you use the following code.
It is a lot easier to remove and show widgets using the .grid method!
Your code:
create_combo[i].destroy()
I assume (as I can see further down the code file) that you used the grid method. In which case I would simply change the code to:
create_combo[i].grid_forget()
Hope This Helps!
From your post:
for i in range(1,count+2):
if (create_combo[i].winfo_exists()):
create_combo[i].destroy()
And the error:
AttributeError: 'str' object has no attribute 'winfo_exists'
I can infer that:Your create_combo must be a list full of string(Instead of Combobox widget).
You could add print(create_combo) before the first for loop to check the value in create_combo.It must be a list full of string.
And it seems that your problem is not here,you should check the way how you create the create_combo.
lets assume create_combo = ['a','b','c']. So I am creating three comboboxes create_combo[0...2]. So name of the comboboxes(widgets) is a, b, c.
No,you couldn't.
If really want to get a list of comboboxes you create,you should use:
create_combo = []
for i in range(3):
t = ttk.Combobox(xxxxx)
t.grid(xxxxxx)
create_combo.append(t) # append it to your create_combo
And then,you could use:
for i in create_combo:
if i.winfo_exists(): # i should be a widget,not string
xxxxxxx # your job
I have a table (grid) I'm creating, constituted of labels.
These labels are showing elements I'm adding to a list, therefore, when I add a new obj to the list, the table will grow, showing more labels.
My intent is that I can click a label and have it print the row of the table that that label is in.
import tkinter as tk
phrasesdb = []
def debug(event):
#this is where I'd have it print the row
#but how do I get it?
#for example, it the label I pressed was in the row 2, it'd print 2
print( ??? )
#Add obj to list
def addline():
##This creates new obj with values from the input fields, and inserts it in the list
newobj = {"text": newtext.get()} #This is getting the text from an Entery
phrasesdb.append(newobj)
##This shows new obj on the table
newesttext = tk.Label(tableframe, text=newobj["text"])
newesttext.grid(row=len(phrasesdb), column=1, sticky=tk.W)
newesttext.bind("<Double-Button-1>", debug)
I'm already able to show them in the table, and to have it recognize I'm pressing the correct label (tested with a simple print("yup, this is it") ), but I'm not being able to figure out how to access the row of the label I'm clicking.
I'm kinda new to python and especially tkinter, so sorry if this is a really easy question, but I'm not finding the answer anywhere else...
You can use the grid_info method which will return a dictionary of the item's grid attributes.
def debug(event):
widget = event.widget
info = widget.grid_info()
row = info['row']
If I understand your problem correctly using .grid_info()['row'] on the label you already received after clicking should return the result you need.