I have a listbox and would like to be able to return multiple selections from said listbox.
I have tried changing "seltext" variable to a list(map(int()))) format, but I get the error of bad listbox index.
I'm not sure how to go about this; any help is appreciated.
The way I'm currently identifying the selected variable:
def selecting(self,event):
sel = self.lbox.curselection()
seltext = self.lbox.get(sel)
self.labelVariable.set(seltext)
The way that I'm assigning a single selection.
def OnButtonClick(self):
global confirmedsel
confirmedsel = ""
sel = self.lbox.curselection()
seltext = self.lbox.get(sel)
confirmedsel = seltext
print(confirmedsel)
app.quit()
The curselection method of the listbox returns a tuple of indexes representing the items that were selected. You simply need to iterate over that list and call the get method to get each element.
You do this in one line using a list comprehension, which results in a list that contains the values of the selected items as strings:
seltext = [self.lbox.get(index) for index in self.lbox.curselection()]
If you find list comprehensions difficult to read, here is a solution using a simple loop:
results = []
for index in self.lbox.curselection():
results.append(self.lbox.get(index))
def selecting(self,event):
sel = self.lbox.curselection()
seltext = list(map(int,self.lbox.get(sel)))
self.labelVariable.set(seltext)
Have you tried this?
You can lookup use of curselection here:
http://effbot.org/tkinterbook/listbox.htm
I'm using a OptionMenu to select an option from a dropdown
self.var = tk.StringVar()
tk.OptionMenu(self, self.var, *self.options)
The options could contain duplicates
Because of this, when I want to know which option is selected I need to know its index in the options list, not just its text.
self.options.index(self.var.get())
However this is O(n) and also fails with duplicates.
How can I find out the index of the select object in a way that works with duplicates (efficiency preferred but not required)?
Unfortunately, this seems impossible.
However, I was able to get an (ugly) workaround. It is based upon ttk.Combox (of which the entry-part is disabled). This method attaches a counter to every option at the very end. Due to the final width of the widget-display, that counter is not shown.
It gets the index rather efficiently, but due to extra whitespaces, storage of memory might not be optimal....
import tkinter as tk
from tkinter import ttk
def set_index(text):
output=()
counter=0
for s in text:
output += (s.ljust(width+extra_whitespace)+str(counter),)
counter += 1
return output
def get_index(*x):
s= OptionVar.get()
a = int(s[s.rfind(" "):])
print(a)
return a
root = tk.Tk()
text = ("a","a","a","a","d","g","fgggggggh","j","a","l","p","a","d","D")
# not entirely sure if width is based on character_width
# you should adjust these nubmer to your own needs....
width = max(map(len,text)) + 3
extra_whitespace = 20
text_with_index = set_index(text)
OptionVar = tk.StringVar()
OptionVar.set(text_with_index[0])
OptionVar.trace("w", get_index)
O = ttk.Combobox(root, textvariable=OptionVar, values=text_with_index)
O.pack()
O.configure(width=width)
O.configure(state="readonly")
get_index()
root.mainloop()
(suggestion; you can adjust the font as well... this can make it easier to adjust width and extra_whitespace)
int(np.argwhere(List==value))
is close but fails to recognize duplicates
I know I'm a bit late to this party, but I was searching for the same thing, couldn't find it so I did the following:
You can inherit a widget in a new class and create a new object that you can customize.
import tkinter
class MyOptionMenu(tkinter.OptionMenu):
"""
An implementation of the tkinter OptionMenu, which inherets tkinter.OptionMenu.
It gives you the ability to add / remove items from the Option List,
Get Options from the List,
Get the Number of Options in the list
Return the selected Option Value and selected Option Index
Methods
-------
SelectOption(Index)
Selects an Option in the OptionMenu specified by the Index integer
AddOptions(LstOptions)
Adds options to the OptionMenu speciefied by lstOptions list
AddOption(Option)
Adds the option to the OptionMenu specified by Option string
DeleteOption(Index)
Deletes an option from the OptionMenu specified by the Index integer
DeleteOptions()
Deletes all options from the OptionMenu
GetOption(Index)
Returns the option as a string specified by the Index integer
GetOptions()
Returns all the options contained in the OptionMenu as a list of strings
GetNumberOrOptions()
Returns the total number of Options contained in the OptionMenu
RenameOption(Index, Option)
Renames an Option to match the Option string specified by the Index integer
"""
def __init__(self, parent, StrVar=None, IntVar=None, LstOptions=None, DefaultValue="", command=None):
"""
Parameters
----------
parent : tkinter.TK
the parent container of the OptionMenu
StrVar : tkinter.StringVar()
the tkinter string variable used to get / set the selected Option's value
IntVar : tkinter.IntVar()
the tkinter integer variable used to get / set the selected Option's index
LstOptions : list
the List of strings used to display the Options in the OptionMenu
DefaultValue : str
the string used to display a default value in the Option Menu if nothing is selected
this can happen if the object initializes with no selected value
this can happen if the selected option is deleted
this can happen if an index is selected that does not exist
command : function(Option, Index)
the function to be called with the parameters Option and Index.
This function is called when an Option is selected and the selected Option Value and Option Index is returned through the functoin
"""
if (StrVar is None):
self.__StrVar = tkinter.StringVar()
else:
self.__StrVar = StrVar
if (IntVar is None):
self.__IntVar = tkinter.IntVar()
else:
self.__IntVar = IntVar
self.__IntVar.trace("w", self.__evtIntVarSet__)
self.__StrVar.set(DefaultValue)
self.__DefaultValue = DefaultValue
super().__init__(parent, value="",variable=StrVar)
self.__command = command
self.__lstOptions = LstOptions
self.__menu = self["menu"] #Get the Menu Object from the OptionMenu Object
self.__menu.delete(0, "end") #Delete all of the Objects contained inside the OptionMenu Object
#Loop through each of the values contained in the list and generate buttons on the menu
#Assign the Button Label and Command function to return the value and the index
for index, value in enumerate(LstOptions):
self.__MenuAdd__(value, index)
def __MenuAdd__(self, value, index):
"""__Internal Function__ that Adds a Menu Command to the Option Menu
This function assigns the Menu Button Label text,
and command that assigns the selected value and index to the tkinter
String and Intiger values. Also combine the callback command function specified
Parameters
----------
value : str
The value used to display the Option Command Label string
Also used for the command callback function specified to indicate which Option was selected
index : int
The index used to for the command callback function specified to indicate which Option was selected by index
"""
self.__menu.add_command(label=value,
command=lambda value=value, index=index: [self.__StrVar.set(value),
self.__IntVar.set(index),
self.__command(value, index)])
def __MenuEdit__(self, value, index):
"""__Internal Function__ that Modifies a Menu Command in the Option Menu
This function assigns the Menu Button Label text,
and command that assigns the selected value and index to the tkinter
String and Intiger values. Also combine the callback command function specified
Parameters
----------
value : str
The value used to display the Option Command Label string
Also used for the command callback function specified to indicate which Option was selected
index : int
The index used to for the command callback function specified to indicate which Option was selected by index
"""
self.__menu.entryconfigure(index,
label=value,
command=lambda value=value, index=index: [self.__StrVar.set(value),
self.__IntVar.set(index),
self.__command(value, index)])
def __evtIntVarSet__(self, var, index, mode):
"""__Internal Function__ that executes when the IntVar changes
This function assigns StrVar value based on the Option specified by the Index specified by IntVar
It is used so that the selected option can be set by index
"""
self.SelectOption(self.__IntVar.get())
def SelectOption(self, Index):
"""Selects the Option in the Option Menu based on the Index integer
If the Index is out of range the DefaultValue string is applied
Parameters
----------
index : int
The index used to select the Option in the Option Menu
"""
if self.GetNumberOfOptions() >= Index >= 0:
self.__StrVar.set(self.GetOption(Index))
else:
self.__StrVar.set(self.__DefaultValue)
def AddOptions(self, LstOptions):
"""Adds Options to the OptionMenu
Parameters
----------
LstOptions : list
A list of strings to be added as Options to the OptionMenu
"""
for Option in LstOptions:
self.AddOption(Option)
def AddOption(self, Option):
"""Adds a Option to the OptionMenu
Parameters
----------
Option : str
An Option to be added to the OptionMenu
"""
index = len(self.__lstOptions) #Get the index value to return (The length of the list of Options)
self.__lstOptions.append(Option)
self.__MenuAdd__(Option, index)
def DeleteOption(self, Index):
"""Deletes an Option from the OptionMenu by the Index Position
Parameters
----------
Index : int
The position of the Option to be deleted from the OptionMenu
"""
del self.__lstOptions[Index] #Delete the Option from the Option List with the specified Index
self.__menu.delete(Index) #Delete the Object from the Option List with the specified Index
if Index == self.__IntVar.get(): #This means the selected Option is being deleted
self.__StrVar.set(self.__DefaultValue) #Assign the default value
else:
if Index > self.__IntVar.get(): #If the Index is greater than the selected index
self.__IntVar.set(Index -1) #This means that the selected index is decremented by one.
#Need to loop through the remainder to update the indexes
for i, value in enumerate(self.__lstOptions):
if i >= Index:
self.__MenuEdit__(value, i)
def DeleteOptions(self):
"""Deletes all Options of the OptionMenu
"""
self.__lstOptions = [] #Clear the Options List
self.__menu.delete(0, "end") #Delete all of the Objects contained inside the OptionMenu Object
self.__StrVar.set(self.__DefaultValue) #The Option is deleted set the Default Value in the OptionMenu
def GetOption(self, Index):
"""Returns a Option Label Value of the Specified Index
Parameters
----------
Index : int
The position of the Option to have the Label Value returned from the OptionMenu
Returns
-------
str
The Option Label Value of the specified by the Index
"""
return self.__lstOptions[Index]
def GetOptions(self):
"""Returns a list of Option Label Value
Returns
-------
list
A List of Strings of the Option Label Values
"""
return self.__lstOptions
def GetNumberOfOptions(self):
"""Returns the total number of Options contained in the OptionMenu
Returns
-------
int
The total number of Options contained in the OptionMenu
"""
return len(self.__lstOptions)
def RenameOption(self, Index, Option):
"""Renames an Option Label Value of the Specified Index
Parameters
----------
Value : str
The value used to display the Option Command Label string
Also used for the command callback function specified to indicate which Option was selected
Index : int
The position of the Option to have the Label Value renamed
"""
self.__lstOptions[Index] = Option #Change the Option at the index
self.__MenuEdit__(Option, Index)
self.SelectOption(self.__IntVar.get()) #Update the Selected Option based on the current IntVar. This is incase the selected Option is Renamed
Created myComboBox with:
myComboBox = QtGui.QComboBox()
Populated it with three items:
myItemsList = ['item01', 'item02', 'item03']
for item in myItemsList:
myComboBox.addItem(item)
Now I want to set a comboBox to a second item knowing only string value of the item: 'item02'.
Let's assume I can't index myItemsList to find out what indexed position of an item with a value 'item02'.
I want to set a myComboBox without using an item index number but its string value. Thanks in advance!
Use QComboBox.findText:
index = myComboBox.findText('item02')
How to get index of current selected row in Gtk.TreeView in Python ?
The other answer is likely more useful in general. However, to answer the actual question posed by the OP, how to get the row index: assuming one row is selected, you can get it with:
index = treeview.get_selection().get_selected_rows()[1][0][0]
You can call gtk.TreeView.get_selection to get the current selection (gtk.TreeSelection). You can then call gtk.TreeSelection.get_selected to get:
a 2-tuple containing a reference to the gtk.TreeModel and a gtk.TreeIter pointing to the currently selected node.
The iter can be used on a gtk.TreeModel (which is obtained by calling gtk.TreeView.get_model. You can then use gtk.TreeModel.get_value to get any of the column values of the node at that position in the tree.
Somewhat late, perhaps not so relevant, but if you have double clicked on the selected row you will get the row index as element of the TreePath tuple, like so
def on_row_activated(self, treeview, path, column):
model = self.treeview.get_model()
tree_iter = model.get_iter(path)
row = path[0]
if tree_iter:
# here you can get the values of the columns
Say I have a dictionary full of parameters:
{speed = 1, intelligence = 3, dexterity = 2}
I want to call a loop that creates a Label and a SpinBox for each item in this list procedurally, in case I want to add more attributes later. I can create the window and return the updated values just fine. My only issue is that I want all the widgets to be created as necessary, whether I have 7 or 20 attributes to edit.
So the label object could be called speed_Label and the intelligence label object intelligence_Label, and the spinbox containing the value of speed would be speed_SpinBox and so on, which then I could pass back easily. However, this
a) seems like poor naming practice
b) seems difficult seeing as I can't find out how to give objects names procedurally, say
for KEY in dict.keys(): # say the KEY is "Speed"
# this would produce a Label object called Speed_Label
# which displays the text "Speed"
"KEY" + "_Label" = QLabel("KEY")
Why not simply use a list or dict?
Something like this should work:
widgets = {}
form = QFormLayout()
for key, value in your_dict.iteritems():
widgets[key] = widget = {}
widget['spinbox'] = spinbox = QSpinBox()
spinbox.setValue(value)
form.addRow(key, spinbox)