Set OptionMenu by index - python

I'm trying to set the value in an OptionMenu by the index of the options, and not use the actual option value itself.
For example, if my OptionMenu has options ["one", "two", "three"], I want to be able to set it to "one" by writing My_Option_Menu.set(options[0]), not My_Option_Menu.set("one")
The OptionMenu is dynamically populated by a list depending on what two other OptionMenus are set to, which is why I want to refer to the options by index and not actual value. Does the OptionMenu object have a way to return the list of options that are currently populated so that my options[0] method above will work?

The simplest way to do this is to keep a copy of the list used to define the optionmenu. Then you can use the index to get the value from the list and assign it to the associated variable.
For example:
options = ["one","two","three"]
...
self.menuVar = tk.StringVar(master)
self.optionMenu = tk.OptionMenu(master, self.menuVar, *options)
...
self.menuVar.set(options[0])
Another option is to get the menu object associate with the widget, and use menu commands to get the text at the given index, and use that to set the variable:
value = self.optionMenu["menu"].entrycget(0, "label")
self.menuVar.set(value)

Related

How to a convert a listbox item's name to a label in Python

For the program that I am required to write up, I need the name of a Listbox item to also be the text in the label. This is the code that I thought would work, but it only configurated the label to be the item's number in the Listbox, not the name:
def openAccount(self):
selectedItem = ltboxSrcUser.curselection()
for item in selectedItem:
rootMainPage.withdraw()
rootOthAccPage.deiconify()
lblOtherUserName.config(text = ltboxSrcUser.curselection())
Can anybody help me out?
The documentation for the listbox shows that curselection returns the index of the selected items, not the values. To get the values you must pass the index to the get method.
def openAccount(self):
selectedItems = ltboxSrcUser.curselection()
if selectedItems:
rootMainPage.withdraw()
rootOthAccPage.deiconify()
index = selectedItems[0]
item = ltboxSrcUser.get(index)
lblOtherUserName.config(text=item)

How to make each radiobutton unique from the others in tkinter

I have a window in Tkinter that looks like this:
When i click on a button in the first row, it stays. However, when i click on a button in the second row, it unselects the one i chose above.
I want it to be able to only select one option per row. Is there something I'm missing? When it's done, I want to be able to iterate over the rows and get the value of the boxes, but I'm not sure how to do that either.
The code for that section is:
for i in studentList:
Label(left,text=i[0][::]+' ' + i[1][::],fg='black',bg='#dbdbdb',font=('Arial',11,'bold')).grid(row=counter,column=0,pady=13,sticky='news')
P = Radiobutton(right,text='Present',bg='#56ab32',fg='black',value='P'+str(counter),indicatoron = 0,font=('Arial',12,'bold'))
P.grid(row=counter,column=0,pady=10,padx=20,sticky='news')
L = Radiobutton(right,text='Leave',bg='#e6a800',fg='white',indicatoron = 0,value='L'+str(counter),font=('Arial',12,'bold'))
L.grid(row=counter,column=1,pady=10,padx=20,sticky='news')
Radiobutton(right,text='Absent',bg='#bd2900',fg='white',indicatoron = 0,value='A'+str(counter),font=('Arial',12,'bold')).grid(row=counter,column=2,pady=10,padx=20,sticky='news')
counter+=1
Radiobuttons work by assigning two or more radiobuttons the same instance of one of tkinter's special variable objects -- usuallyStringVar or IntVar. This sharing of a variable is what makes a group of radiobuttons work as a set, since the variable can only hold a single value.
Because you aren't assigning a variable, tkinter is using a default variable which is the same for every button. Thus, all buttons are acting as a single set.
To make your code work, each row needs to use it's own instance of StringVar. It would look something like this:
vars = []
for i in studentList:
var = StringVar()
vars.append(var)
...
Radiobutton(right, variable=var, ...)
Radiobutton(right, variable=var, ...)
Radiobutton(right, variable=var, ...)
...
With the above, you can get the choice of each row by getting the value of the variable for that row. For example, the first row would be vars[0].get(), the second row would be vars[1].get() and so on.

Label text changing when dictionary is updated

I'm new to coding and i've been messing around with tkinter.
My labels have text, that is supposed to change when the dictionary values are updated.
An example of my code:
def setit(point, adic,number):
adic[point] = adic[point]+number
dict={'a':4,'b':8,'c':3}
aa=Label(root,text=dict['a']).pack()
bb=Label(root,text=dict['b']).pack()
cc=Label(root,text=dict['c']).pack()
Button(command=setit('a',dict,3)).pack()
When the button is pressed i want both the dictionary and the appropriate Label to update. How would you do that? Preferably without OOP. Thanks!
First of all, there are two problems in your code sample:
1) .pack() returns None, so when you do aa=Label(root,text=dict['a']).pack(), you store None in the variable aa, not the label. You should do:
aa = Label(root,text=dict['a'])
aa.pack()
2) The command option of a button takes a function as argument but you do command=setit('a',dict,3) so you execute the function at the button creation. To pass a function with arguments to a button command, you can use a lambda:
Button(command=lambda: setit('a',dict,3))
Then, to update the label when the value in the dictionary is changed, you can store your labels in a dictionary with the same keys and change the text of the appropriate label with label.configure(text='new value'):
import tkinter as tk
def setit(point, adic, label_dic, number):
adic[point] = adic[point] + number # change the value in the dictionary
label_dic[point].configure(text=adic[point]) # update the label
root = tk.Tk()
dic = {'a': 4, 'b': 8, 'c': 3}
# make a dictionary of labels with keys matching the ones of dic
labels = {key: tk.Label(root, text=dic[key]) for key in dic}
# display the labels
for label in labels.values():
label.pack()
tk.Button(command=lambda: setit('a', dic, labels, 3)).pack()
root.mainloop()
You can use a StringVar instead of specifying the text value. That looks like:
d={'a':StringVar(),'b':StringVar(),'c':StringVar()}
aa=Label(root,textvariable=d['a'])
bb=Label(root,textvariable=d['b'])
cc=Label(root,textvariable=d['c'])
aa.pack()
bb.pack()
cc.pack()
And then whenever you want to change the label, you can do
d['a'].set("new text!")
See here for more info on labels.
Note: dict is a reserved word in python, so it's best to not use that as the name of your variable. Same goes for str, int, etc.

Retrieve text from entry widget Tkinter

So I know how to retrieve the text from a single entry widget using the get function but now I am trying to create multiple entry widgets at the same time using a for loop. How can I go back and retrieve the text from anyone of the entry widgets once the user types in them?
rows=11
for line in range(10):
rows=rows+1
widget = Tk.Entry(self.frame)
widget.grid(row=rows, column=5)
The problem is that all of your widget objects are being assigned to a reference, and with each next iteration of the loop are being unreferenced. A way to fix this is to create a list and add these widgets to the list:
entries = []
for line in range(10):
rows = rows + 1
widget = Tk.Entry(self.name)
widget.grid(row = rows, column = 5)
entries.append(widget) # Add this line to your code
Now, to access a specific entrybox, you just find it in the array. So, for example, the second box will be found at entries[1] (because it is 0-based).
The fundamental problem you're having is that you don't have any sort of data structure. Are you familiar with the list type?
rows=11
entries = [Tk.Entry(self.frame) for item in range(10)]
for item in entries:
rows=rows+1
item.grid(row=row, column=5)
This creates a list of Entry widgets, then goes through that list and grids each one into a row (starting with 12). You can access list items by index, e.g. entries[0] for the first Entry.
widgets = []
for i in range(11, 23):
widgets.append(Tk.Entry(self.frame))
widget[i-11].grid(row = i, column = 5)
To answer your question directly, you need the get() method, which is available to the Entry class. To get the value of your widget object, the code would look something like this:
myValue = widget.get()
Please note that, as others have mentioned, your "for" loop does not actually create 10 Entry objects. Since you keep reassigning your new Entry objects to the variable "widget", the old Entry object you created gets de-referenced. Instead of assigning each new Entry object to the variable "widget", append them to a list instead.

Change Listbox items based on selection in another Listbox

I am trying to dynamically change the entries in a Listbox (lb_ledgers) depending on the selection in another Listbox (lb_book). I currently have the following lines of code:
lb_book.bind('<<ListboxSelect>>', onselect)
def onselect(evt):
w = evt.widget
index = int(w.curselection()[0])
value = w.get(index)
The problem is that I do not know how to pass the first Listbox (lb_ledgers) to the function onselect in order to change its contents. I have tried using a lambda construct, but that did not work. Could you please let me know how to solve this?
Thanks,
MiddleClassMan

Categories

Resources