How can I create a single Tkinter Listbox with line breaks?

I have a work object Tkinter.Listbox, but I want to configure it so that its elements can have a carriage return without the need to somehow configure several related elements.

For example, if I want to create a selection bar with elements that look like this.

    # Here are four elements for the selector Listbox..
lb_items = ('mama', 'luigi', 'my birds', \
            'this is a single element\n spanning two lines!')
    # This generates and displays the selector window..
tk_selector = SingleSelect(lb_items, "TEST SELECTOR")
tk_selector.run_selector()

.. it would be great if I could get an output similar to this layout.

nb: it's just a layout

.. instead of what it actually generates, that is ..

you cannot see it, but it is all one line.

Listboxes seem to ignore strings '\n'and triple quotes with string returns; if used \n, neither characters nor line breaks are displayed.

Is it possible to have separate, selectable list items that appear with line breaks?

" ", ​​ Listbox Tk .

, , , , , - , -, .

+4
2

, Listbox, "" , , , .

, "" , Listbox, splitlines, , , string, , Listbox Listbox.bind('<<ListboxSelect>>', self._reselection_fxn).


class Multiline_Single_Selector(object):
      ## Go ahead and choose a better class name than this, too. :/
    def __init__(self, itemlist, ..):
              # ..
        lb_splitlines = self._parse_strings(itemlist) 
          # ^ splits the raw strings and records their indices.
          #  returns the split strings as a list of Listbox elements.
        self.my_Listbox.insert(0, *lb_splitlines) 
          # ^ put the converted strings into the Listbox..

        self.my_Listbox.bind('<<ListboxSelect>>', self._reselect)
          # ^ Whenever the Listbox selection is modifed, it triggers the
          #  <<ListboxSelect>> event. Bind _reselect to it to determine
          #  which lines ought to be highlighted when the selection updates.
              # ..

    def _parse_strings(self, string_list):
        '''Accepts a list of strings and breaks each string into a series of lines,
logs the sets, and stores them in the item_roster and string_register attributes.
Returns the split strings to be inserted into a Listbox.'''

        self.index_sets = index_sets = []
          # ^ Each element in this list is a tuple containing the first and last
          #  Listbox element indices for a set of lines. 

        self.string_register = register = {}
          # ^ A dict with a whole string element keyed to the index of the its
          #  first element in the Listbox.

        all_lines = [] 
          # ^ A list of every Listbox element. When a string is broken into lines,
          #  the lines go in here.

        line_number = 0
        for item in string_list: 
            lines = item.splitlines()

            all_lines.extend(lines) # add the divided string to the string stack
            register[line_number] = item
                # ^ Saves this item keyed to the first Listbox element it associated
                #  with. If the item is selected when the Listbox closes, the original 
                #  (whole) string is found and returned based on this index number.

            qty = len(lines)
            if qty == 1: # single line item..
                index_sets.append((line_number, line_number))
            else: # multiple lines in this item..
                element_range = line_number, line_number + qty - 1 
                  # ^ the range of Listbox indices..
                index_sets.extend([element_range] * qty) 
                  # ^ ..one for each element in the Listbox.

            line_number += qty # increment the line number.
        return all_lines

    def _reselect(self, event=None):
        "Called whenever the Listbox selection changes."
        selection = self.my_Listbox.curselection() # Get the new selection data.
        if not selection: # if there is nothing selected, do nothing.
            return

        lines_st, lines_ed = self.index_sets[selection[0]]
            # ^ Get the string block associated with the current selection.
        self.my_Listbox.selection_set(lines_st, lines_ed) 
            # ^ select all lines associated with the original string.

    def _recall(self, event=None):
        "Get the complete string for the currently selected item."
        selection = self.my_Listbox.curselection()
        if selection: # an item is selected!
            return self.string_register[selection[0]]
        return None   # no item is selected.

Listbox, . , line-wrap \n -parsing Listbox, .

, , _recall , . None, .

, , . .

+2

, .

+1

Source: https://habr.com/ru/post/1671839/


All Articles