class TkUserListSelect(object): """ A simple box to pop up for user based item selection. This is not for file or file path selection, there is another class for that Example ------- >>> user_list_box = TkUserListSelect(title='Title', >>> message='Info For User', >>> user_enum=dict( >>> zip([1, 'hi', 'user sees these', 4], >>> [1, 'user doesnt see these', >>> 'but they correspond with the keys that the user does see', >>> ' 1:1 by location and are what are returned if desired']))) >>> user_list_box.open_frame() ...Interaction (user selects 'hi') >>> user_list_box.return_index() 1 >>> user_list_box.return_index_value() 'hi' >>> user_list_box.return_enum() {'hi': 'user doesnt see these'} >>> user_list_box.return_value() 'user doesnt see these' """ def __init__(self, title, message, user_enum): self.master = Tk() self.value = None self._user_presented_list = list(user_enum.keys()) self._short_bubble_sort() self._user_enum = user_enum self._current_font_type = 'Times' self._current_font_size = 10 self.font_obj = font.Font(font=(self._current_font_type, self._current_font_size)) # self.modalPane = Toplevel(self.master) self.modalPane = self.master # self.modalPane.transient(self.master) self.modalPane.grab_set() self.modalPane.bind("<Return>", self._choose) self.modalPane.bind("<Escape>", self._cancel) if title: self.modalPane.title(title) if message: self.message_label = \ Label(self.modalPane, text=message) self.message_label.pack(padx=5, pady=5) listFrame = Frame(self.modalPane) listFrame.pack(side=TOP, padx=5, pady=5) scrollBar = Scrollbar(listFrame) scrollBar.pack(side=RIGHT, fill=Y) self.listBox = Listbox(listFrame, selectmode=SINGLE) self.listBox.pack(side=LEFT, fill=Y) scrollBar.config(command=self.listBox.yview) self.listBox.config(yscrollcommand=scrollBar.set) # self.list.sort() for item in self._user_presented_list: self.listBox.insert(END, item) buttonFrame = Frame(self.modalPane) buttonFrame.pack(side=BOTTOM) chooseButton = Button(buttonFrame, text="Choose", command=self._choose) chooseButton.pack() cancelButton = Button(buttonFrame, text="Cancel", command=self._cancel) cancelButton.pack(side=RIGHT) self.set_font_size('Times', 10) self.autowidth(500) def set_font_size(self, FONT_TYPE, FONT_SIZE): self._current_font_type = FONT_TYPE self._current_font_size = FONT_SIZE self.font_obj = font.Font(font=(self._current_font_type, self._current_font_size)) self.message_label.config(font=(self._current_font_type, self._current_font_size)) self.listBox.config(font=(self._current_font_type, self._current_font_size)) def autowidth(self, maxwidth): pixels = 0 for item in self.listBox.get(0, "end"): pixels = max(pixels, self.font_obj.measure(item)) # bump listbox size until all entries fit pixels = pixels + 10 width = int(self.listBox.cget("width")) for w in range(0, maxwidth + 1, 5): if self.listBox.winfo_reqwidth() >= pixels: break self.listBox.config(width=width + w) def _short_bubble_sort(self): exchanges = True passnum = len(self._user_presented_list) - 1 while (passnum > 0) and exchanges: exchanges = False for i in range(passnum): try: if len(self._user_presented_list[i]) > \ len(self._user_presented_list[i + 1]): exchanges = True self._user_presented_list[i], self._user_presented_list[i + 1] = \ self._user_presented_list[i + 1], self._user_presented_list[i] except TypeError as e: pass passnum = passnum - 1 def open_frame(self): self.master.mainloop() def _choose(self, event=None): try: firstIndex = self.listBox.curselection()[0] self.index = firstIndex self.index_value = self._user_presented_list[int(firstIndex)] except IndexError: self.index_value = None self.modalPane.destroy() def _cancel(self, event=None): self.modalPane.destroy() def return_index_value(self): return self.index_value def return_index(self): return self.index def return_enum(self): return {self.index_value: self._user_enum[self.index_value]} def return_value(self): return self._user_enum[self.index_value]