|
| 1 | +import logging |
1 | 2 | import tkinter as tk |
2 | 3 | import tkinter.ttk as ttk |
3 | | -import logging |
| 4 | +from typing import List |
| 5 | + |
4 | 6 |
|
5 | 7 | logger = logging.getLogger(__name__) |
6 | 8 |
|
@@ -180,6 +182,105 @@ def internal_callback(*args): |
180 | 182 | self._var.trace('w', internal_callback) |
181 | 183 |
|
182 | 184 |
|
| 185 | +class SmartListBox(SmartWidget): |
| 186 | + """ |
| 187 | + Easy-to-use List Box. Takes most options that work with |
| 188 | + a normal CheckButton. Attempts to call your callback |
| 189 | + function - if assigned - whenever there is a change to |
| 190 | + the list box selections.:: |
| 191 | +
|
| 192 | + # create the smart spinbox and grid |
| 193 | + scb = SmartListBox(root, options=['one', 'two', 'three']) |
| 194 | + scb.grid() |
| 195 | +
|
| 196 | + # define a callback function that retrieves |
| 197 | + # the currently selected option |
| 198 | + def callback(): |
| 199 | + print(scb.get_selected()) |
| 200 | +
|
| 201 | + # add the callback function to the checkbutton |
| 202 | + scb.add_callback(callback) |
| 203 | +
|
| 204 | + :param parent: the tk parent frame |
| 205 | + :param options: any options that are valid for tkinter.Checkbutton |
| 206 | + :param on_select_callback: python callable |
| 207 | + :param selectmode: the selector mode (supports "browse" and "multiple") |
| 208 | + """ |
| 209 | + def __init__(self, parent, options: List[str], |
| 210 | + width: int = 12, height: int = 5, |
| 211 | + on_select_callback: callable = None, |
| 212 | + selectmode: str = 'browse'): |
| 213 | + super().__init__(parent=parent) |
| 214 | + |
| 215 | + self._on_select_callback = on_select_callback |
| 216 | + self._values = {} |
| 217 | + |
| 218 | + r = 0 |
| 219 | + self._lb = tk.Listbox(self, width=width, height=height, selectmode=selectmode, exportselection=0) |
| 220 | + self._lb.grid(row=r, column=0, sticky='ew') |
| 221 | + [self._lb.insert('end', option) for option in options] |
| 222 | + self._lb.bind('<<ListboxSelect>>', lambda _: self._on_select()) |
| 223 | + |
| 224 | + r += 1 |
| 225 | + clear_label = tk.Label(self, text='clear', fg='blue') |
| 226 | + clear_label.grid(row=r, column=0, sticky='ew') |
| 227 | + clear_label.bind('<Button-1>', lambda _: self._clear_selected()) |
| 228 | + |
| 229 | + def _on_select(self): |
| 230 | + self.after(200, self.__on_select) |
| 231 | + |
| 232 | + def _clear_selected(self): |
| 233 | + for i in self._lb.curselection(): |
| 234 | + self._lb.selection_clear(i, 'end') |
| 235 | + |
| 236 | + while len(self._values): |
| 237 | + self._values.popitem() |
| 238 | + |
| 239 | + if self._on_select_callback is not None: |
| 240 | + self._on_select_callback() |
| 241 | + |
| 242 | + def __on_select(self): |
| 243 | + value = self._lb.get('active') |
| 244 | + |
| 245 | + if self._lb.cget('selectmode') == 'multiple': |
| 246 | + if value in self._values.keys(): |
| 247 | + self._values.pop(value) |
| 248 | + else: |
| 249 | + self._values[value] = True |
| 250 | + else: |
| 251 | + while len(self._values): |
| 252 | + self._values.popitem() |
| 253 | + self._values[value] = True |
| 254 | + |
| 255 | + if self._on_select_callback is not None: |
| 256 | + values = list(self._values.keys()) |
| 257 | + try: |
| 258 | + self._on_select_callback(values) |
| 259 | + except TypeError: |
| 260 | + self._on_select_callback() |
| 261 | + |
| 262 | + def add_callback(self, callback: callable): |
| 263 | + """ |
| 264 | + Associates a callback function when the user makes a selection. |
| 265 | +
|
| 266 | + :param callback: a callable function |
| 267 | + """ |
| 268 | + self._on_select_callback = callback |
| 269 | + |
| 270 | + def get_selected(self): |
| 271 | + return list(self._values.keys()) |
| 272 | + |
| 273 | + def select(self, value): |
| 274 | + options = self._lb.get(0, 'end') |
| 275 | + if value not in options: |
| 276 | + raise ValueError('Not a valid selection') |
| 277 | + |
| 278 | + option = options.index(value) |
| 279 | + |
| 280 | + self._lb.activate(option) |
| 281 | + self._values[value] = True |
| 282 | + |
| 283 | + |
183 | 284 | class BinaryLabel(ttk.Label): |
184 | 285 | """ |
185 | 286 | Displays a value binary. Provides methods for |
|
0 commit comments