How to set the selection bar based on the index of the shuffled items in the tkinter listbox

Viewed 43

How do I let .selection_set() set the selection bar to the selected shuffled item in the listbox? Using .curselection()[0] only returns the index of the current selected item in the listbox, but when I place a button that links to the shuffled items of the listbox, the selection bar isn't set according to the selected item. What I'm trying to achieve is something like a next button, .curselection()[0] + 1. But instead of going down the list, I need it to go according to the selected shuffled item, something like .curselection()[0] + "the index of the selected shuffled item". Below is a runnable code of what I'm trying to explain:

import tkinter as tk
from random import shuffle

root = tk.Tk()
root.geometry('300x200')
root.resizable(False, False)
root.title('Listbox')

is_shuffling = False
item_index = 0

langs = ['Java', 'C#', 'C', 'C++', 'Python',
        'Go', 'JavaScript', 'PHP', 'Swift']

langs_var = tk.StringVar(value=langs)

listbox = tk.Listbox(root, listvariable=langs_var, height=6)

listbox.grid(column=0, row=0, sticky='nwes')

bottom_frame = tk.Frame()
bottom_frame.grid(row=1, column=0, sticky="ew")
bottom_frame.grid_columnconfigure(2, weight=1)
bottom_frame.grid_rowconfigure(0, weight=1)
root.rowconfigure(0, weight=1)
root.columnconfigure(0, weight=1)


shuffle(langs)

def go_next():
    global is_shuffling
    global langs
    shuffle(langs)
    if is_shuffling:
        item_index = listbox.curselection()[0]
        listbox.selection_clear(0, tk.END)
        listbox.selection_set(item_index)
        listbox.activate(item_index)
        print(langs)
    else:
        try:
            idx = listbox.curselection()[0] + 1
            listbox.selection_clear(0, tk.END)
            listbox.selection_set(idx)
            listbox.activate(idx)
        except IndexError:
            listbox.selection_set(0)
            listbox.activate(0)

def toggle_shuffle():
    global is_shuffling
    if is_shuffling:
        shuffle_btn.config(text="Shuffle Off")
        is_shuffling = False
    else:
        shuffle_btn.config(text="Shuffle On")
        is_shuffling = True

shuffle_btn = tk.Button(bottom_frame, relief=tk.SUNKEN, text="Shuffle", bg="silver", highlightthickness=0, bd=0, command=toggle_shuffle)
shuffle_btn.grid(row=1, column=0)

next_btn = tk.Button(bottom_frame, relief=tk.SUNKEN, text="Next Button", bg="silver", highlightthickness=0, bd=0, command=go_next)
next_btn.grid(row=1, column=1, padx=10)

print(langs)

root.mainloop()

You can see that when the shuffle button is pressed, pressing the next button won't set the selection bar to the selected shuffled item from the list.

1 Answers

You need to get the random index, not shuffle the lists, because shuffling entire list might not be what you want.

from random import randint

def go_next():
    if is_shuffling:
        rand = randint(0,listbox.size()-1) # Get random index within range
        listbox.selection_clear(0, tk.END)
        listbox.selection_set(rand) # Set the index
        listbox.activate(rand)
    else:
        try:
            idx = listbox.curselection()[0] + 1
            listbox.selection_clear(0, tk.END)
            listbox.selection_set(idx)
            listbox.activate(idx)
        except IndexError:
            listbox.selection_set(0)
            listbox.activate(0)
Related