I have made a scrollable frame in tkinter
but there are a few things that aren't working.
-Is there a way to bring the scrollbar
closer to the labels
?
-Is there a way to start the scrollbar
on top and not in the middle?
-When I use bind
I cannot scroll when my mouse is over the labels
, and when I use bind_all
I can scroll everywhere on the window. Is there a way to scroll only when my mouse is above the label
?
My code:
from tkinter import *
class Example:
def __init__(self, root):
self.master = root
self.init_scrollframe()
def init_scrollframe(self):
self.big_frame = Frame(self.master)
self.big_frame.grid(row=0, column=0)
self.title = Label(self.big_frame, text="TITLE", font=("Arial", 30))
self.title.grid(row=0, column=0, columnspan=2)
self.frame = Frame(self.big_frame)
self.frame.grid(row=1, column=0)
self.scrollb = Scrollbar(self.frame, orient=VERTICAL)
self.scrollb.grid(row=0, column=1, sticky=N+S+W)
self.scroll_canvas = Canvas(self.frame, yscrollcommand=self.scrollb.set)
self.scroll_canvas.grid(row=0, column=0, sticky=N+S+E)
self.scrollb.config(command=self.scroll_canvas.yview)
##this doesn't work
"""self.frame.bind("<MouseWheel>", self._on_mousewheel)
self.frame.bind("<Button-5>", self._on_mousewheel)
self.frame.bind("<Button-4>", self._on_mousewheel)"""
##this works but it is scrolling also when I am not above the labels
self.scroll_canvas.bind_all("<MouseWheel>", self._on_mousewheel)
self.scroll_canvas.bind_all("<Button-5>", self._on_mousewheel)
self.scroll_canvas.bind_all("<Button-4>", self._on_mousewheel)
self.my_frame = Frame(self.scroll_canvas)
##put some labels into the scrollable frame
for i in range(100):
self.lbl = Label(self.my_frame, text=str("label number " + str(i)))
self.lbl.grid(row=i, column=0)
self.scroll_canvas.create_window(0, 0, window=self.my_frame)
self.my_frame.update_idletasks()
self.scroll_canvas.config(scrollregion=self.scroll_canvas.bbox("all"))
##this is for scrolling
def _on_mousewheel(self, event):
if event.num == 5 or event.delta == -120:
self.scroll_canvas.yview_scroll(1, "units")
if event.num == 4 or event.delta == 120:
self.scroll_canvas.yview_scroll(-1, "units")
if __name__ == "__main__":
root = Tk()
ex = Example(root)
root.mainloop()
For your 3rd question, you can simply do a check on whether the event is within the frame before your scroll_canvas
.
from tkinter import *
class Example:
def __init__(self, root):
self.master = root
self.init_scrollframe()
def init_scrollframe(self):
self.big_frame = Frame(self.master)
self.big_frame.grid(row=0, column=0)
self.title = Label(self.big_frame, text="TITLE", font=("Arial", 30))
self.title.grid(row=0, column=0, columnspan=2)
self.frame = Frame(self.big_frame,name="test") #give it a name to check
self.frame.grid(row=1, column=0)
self.scrollb = Scrollbar(self.frame, orient=VERTICAL)
self.scrollb.grid(row=0, column=1, sticky=N+S+W)
self.scroll_canvas = Canvas(self.frame, yscrollcommand=self.scrollb.set)
self.scroll_canvas.grid(row=0, column=0, sticky=N+S+E)
self.scrollb.config(command=self.scroll_canvas.yview)
self.scroll_canvas.bind_all("<MouseWheel>", self._on_mousewheel)
self.scroll_canvas.bind_all("<Button-5>", self._on_mousewheel)
self.scroll_canvas.bind_all("<Button-4>", self._on_mousewheel)
self.my_frame = Frame(self.scroll_canvas)
for i in range(100):
self.lbl = Label(self.my_frame, text=str("label number " + str(i)))
self.lbl.grid(row=i, column=0)
self.scroll_canvas.create_window(0, 0, window=self.my_frame)
self.my_frame.update_idletasks()
self.scroll_canvas.config(scrollregion=self.scroll_canvas.bbox("all"))
def _on_mousewheel(self, event):
caller = event.widget
if "test" in str(caller): #check if event is within frame
if event.num == 5 or event.delta == -120:
self.scroll_canvas.yview_scroll(1, "units")
if event.num == 4 or event.delta == 120:
self.scroll_canvas.yview_scroll(-1, "units")
if __name__ == "__main__":
root = Tk()
ex = Example(root)
root.mainloop()
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.