Edmond Cepele
Edmond Cepele

Reputation: 11

Tkinter canvar scroll with mousewheel

I am creating 4 frames and canvas with a for loop and assigning each of them a different scrollbar, i wanted to add the scroll with the mouse wheel and the code i found works fine, but only if the mouse cursor is not overing the labels or other widgeds that might be inside the frame inside the canvas. This is the error that i get AttributeError: 'Label' object has no attribute 'yview_scroll'

    f_s = ['s_one', 's_two', 's_three', 's_four']
    f_o = ['f_one', 'f_two', 'f_three', 'f_four']
    self.f_c = ['c_one', 'c_two', 'c_three', 'c_four']
    self.f_f = ['fs_one', 'fs_two', 'fs_three', 'fs_four']

    def set_mousewheel(widget, command):
        widget.bind("<Enter>", lambda _: widget.bind_all('<MouseWheel>', command))
        widget.bind("<Leave>", lambda _: widget.unbind_all('<MouseWheel>'))

    for f in range(4):
        f_o[f] = Frame(self.f_bot, width=250, height=580, bg=self.bg)
        f_o[f].grid(row=1, column=f)
        f_o[f].grid_propagate(False)
        self.f_c[f] = Canvas(f_o[f], width=229, height=580, bg=self.bg)
        self.f_c[f].pack(side=LEFT, fill=BOTH, expand=1)
        f_s[f] = Scrollbar(f_o[f], orient=VERTICAL, command=self.f_c[f].yview, bg=self.bg)
        f_s[f].pack(side=RIGHT, fill=Y)
        self.f_c[f].configure(yscrollcommand=f_s[f].set)
        self.f_c[f].bind('<Configure>', lambda event: event.widget.configure(scrollregion=event.widget.bbox('all')))
        self.f_f[f] = Frame(self.f_c[f], bg=self.bg)
        self.f_c[f].create_window((0, 0), window=self.f_f[f], anchor='nw')
        self.f_c[f].bind("<Enter>", lambda event: event.widget.bind_all('<MouseWheel>', lambda event: event.widget.yview_scroll(-1 * (event.delta // 120), "units")))
        self.f_c[f].bind("<Leave>", lambda event: event.widget.unbind_all('<MouseWheel>'))

the labels inside the final frames are created with a for loop as well

Upvotes: 0

Views: 45

Answers (1)

Edmond Cepele
Edmond Cepele

Reputation: 11

Found a solution following this thread: Tkinter Scrollbars with labels, canvas and frames

    def scroll(widget, event):
        widget.yview_scroll(int(-1 * (event.delta / 120)), "units")

    def final_scroll(widget, func, *_):
        widget.bind_all("<MouseWheel>", func)

    def stop_scroll(widget, *_):
        widget.unbind_all("<MouseWheel>")

    for f in range(4):
        f_o[f] = Frame(self.f_bot, width=250, height=bot_height, bg=self.bg)
        f_o[f].grid(row=1, column=f)
        f_o[f].grid_propagate(False)
        self.f_c[f] = Canvas(f_o[f], width=229, height=bot_height, bg=self.bg)
        self.f_c[f].pack(side=LEFT, fill=BOTH, expand=1)
        f_s[f] = Scrollbar(f_o[f], orient=VERTICAL, command=self.f_c[f].yview, bg=self.bg)
        f_s[f].pack(side=RIGHT, fill=Y)
        self.f_c[f].configure(yscrollcommand=f_s[f].set)
        self.f_c[f].bind('<Configure>', lambda event: event.widget.configure(scrollregion=event.widget.bbox('all')))
        self.f_f[f] = Frame(self.f_c[f], bg=self.bg)
        self.f_c[f].create_window((0, 0), window=self.f_f[f], anchor='nw')
        self.f_c[f].bind("<Enter>", lambda e: final_scroll(e.widget, lambda event: scroll(e.widget, event), e))
        self.f_c[f].bind("<Leave>", lambda e: stop_scroll(e.widget, e))

Upvotes: 1

Related Questions