Ниже приведен наименьший полнофункциональный код tkinter, который я мог бы написать, чтобы продемонстрировать проблему, с которой я столкнулся в более крупном приложении. Этот код представляет два фрейма: левый содержит список, правый содержит прокручиваемый текстовый виджет. Когда пользователь выбирает элемент списка, содержимое этого элемента отображается в текстовом виджете. Если вы поместите курсор в текстовый виджет, все будет хорошо. Вы можете без проблем добавить больше текста и/или использовать клавишу удаления для удаления текста. Но если вы выбираете любой текст в текстовом виджете, вызывается функция «ListboxSelect» и выдает ошибку «IndexError: индекс кортежа вне диапазона». Это не имеет никакого смысла. Почему выбор текста в текстовом виджете вызывает функцию, которая явно привязана к виджету списка?
import tkinter as tk
from tkinter import scrolledtext
root = tk.Tk()
root.geometry("400x200")
def listbox_selected(event):
w = event.widget
listbox_index = int(w.curselection()[0])
right_text.delete(1.0,tk.END)
right_text.insert(tk.END,left_listbox.get(listbox_index))
left_frame = tk.Frame(root,height=200,width=180,bg = "lightblue")
left_frame.place(x=15,y=2)
# left frame contains listbox
left_listbox = tk.Listbox(left_frame)
left_listbox.bind("<<ListboxSelect>>",listbox_selected)
left_listbox.place(x=5,y=5)
for index in range(5):
left_listbox.insert(index,"This is item " + str(index))
right_frame = tk.Frame(root,height=200,width=180,bg = "lightyellow")
right_frame.place(x=200,y=5)
# right frame contains scrollable text widget
right_text = tk.scrolledtext.ScrolledText(right_frame,width=18,
height=10)
right_text.place(x=5,y=5)
root.mainloop()






Это связано с тем, что при выборе текста внутри Text виджет отменяет выбор выбранного элемента в Listbox, что вызывает событие <<ListboxSelect>>.
Отмену выбора в Listbox можно отключить, установив exportselection=0:
left_listbox = tk.Listbox(left_frame, exportselection=0)
Другой способ — проверить, есть ли внутри listbox_selected() выбранный предмет:
def listbox_selected(event):
w = event.widget
selection = w.curselection()
# check whether there is item selected
if selection:
listbox_index = int(selection[0])
right_text.delete(1.0,tk.END)
right_text.insert(tk.END,left_listbox.get(listbox_index))
На самом деле, при экспериментировании комбинация обоих вариантов работает лучше всего. Если я использую только второе решение (при выборе:)... список становится невыбранным, когда текст выбран в списке. В обоих решениях (exportselection=0 и if selection:) список не становится невыбранным. А функции вырезания и вставки продолжают работать в текстовом виджете. Спасибо еще раз.
@fmex Если это решит ваш вопрос, рассмотрите возможность принять его как ответ.
Где я могу принять это как ответ? Я не вижу такой опции нигде на этой странице, спасибо.
Большое спасибо...много полезной информации. Итак, я предполагаю, что новое утверждение: если выбор: (верно) означает «если есть выбор конкретно в виджете списка?