Вот упрощенная версия кода, демонстрирующая проблему:
Код: Выделить всё
import tkinter as tk
class ScrollableFrame(tk.Tk):
def __init__(self):
super().__init__()
self.canvas = tk.Canvas(self, borderwidth=0)
self.frame = tk.Frame(self.canvas)
self.vsb = tk.Scrollbar(self, orient="vertical", command=self.canvas.yview)
self.canvas.configure(yscrollcommand=self.vsb.set)
self.vsb.pack(side="right", fill="y")
self.canvas.pack(side="left", fill="both", expand=True)
self.canvas_frame = self.canvas.create_window((4,4), window=self.frame, anchor="nw",
tags="self.frame")
self.frame.bind("", self.on_frame_configure)
self.canvas.bind("", self.on_canvas_configure)
self.populate()
def populate(self):
self.labels = []
for i in range(10):
label = tk.Label(self.frame, text=f"Label {i}", bg="white")
label.pack(padx=10, pady=10, fill="x")
self.labels.append(label)
self.scroll_down_button = tk.Button(self, text="Scroll Down", command=self.scroll_down)
self.scroll_down_button.pack(side="left")
self.scroll_up_button = tk.Button(self, text="Scroll Up", command=self.scroll_up)
self.scroll_up_button.pack(side="left")
self.select_button = tk.Button(self, text="Select", command=self.select_label)
self.select_button.pack(side="left")
self.current_label_index = 0
self.highlight_label(self.current_label_index)
def on_frame_configure(self, event):
self.canvas.configure(scrollregion=self.canvas.bbox("all"))
def on_canvas_configure(self, event):
canvas_width = event.width
self.canvas.itemconfig(self.canvas_frame, width=canvas_width)
self.update_scroll_position()
def update_scroll_position(self):
# Get the current view position of the scrollbar
current_view = self.canvas.yview()
# Calculate the position of the current label
label_y = self.labels[self.current_label_index].winfo_y()
# Calculate the height of the frame
frame_height = self.frame.winfo_height()
# Calculate the new position for the scrollbar thumb
new_position = label_y / frame_height
# Set the scrollbar to the new position
self.canvas.yview_moveto(new_position)
def scroll_down(self):
if self.current_label_index < len(self.labels) - 1:
self.unhighlight_label(self.current_label_index)
self.current_label_index += 1
self.highlight_label(self.current_label_index)
self.canvas.yview_scroll(1, "units")
def scroll_up(self):
if self.current_label_index > 0:
self.unhighlight_label(self.current_label_index)
self.current_label_index -= 1
self.highlight_label(self.current_label_index)
self.canvas.yview_scroll(-1, "units")
def select_label(self):
label_text = self.labels[self.current_label_index].cget("text")
print(label_text)
def highlight_label(self, index):
self.labels[index].configure(bg="yellow")
def unhighlight_label(self, index):
self.labels[index].configure(bg="white")
if __name__ == "__main__":
app = ScrollableFrame()
app.mainloop()
Что я пробовал до сих пор:
- Привязка метода к событию холста для обновления области прокрутки.
< li>Настройка представления холста в методах Scroll_up и Scroll_down.
Подробнее здесь: https://stackoverflow.com/questions/784 ... nter-windo