5

Is there a way to add a scrollbar to my entire window without putting everything into a frame? I've set everything up with .grid, and I don't like the idea of wrapping a frame around everything.

root = Tk() root.maxsize(900,600) circus()#calls the function to set up everything root.mainloop() 
1

6 Answers 6

6

How to add scrollbars to full window in tkinter ?

here is the answer for python 3...

 from tkinter import * from tkinter import ttk root = Tk() root.title('Full Window Scrolling X Y Scrollbar Example') root.geometry("1350x400") # Create A Main frame main_frame = Frame(root) main_frame.pack(fill=BOTH,expand=1) # Create Frame for X Scrollbar sec = Frame(main_frame) sec.pack(fill=X,side=BOTTOM) # Create A Canvas my_canvas = Canvas(main_frame) my_canvas.pack(side=LEFT,fill=BOTH,expand=1) # Add A Scrollbars to Canvas x_scrollbar = ttk.Scrollbar(sec,orient=HORIZONTAL,command=my_canvas.xview) x_scrollbar.pack(side=BOTTOM,fill=X) y_scrollbar = ttk.Scrollbar(main_frame,orient=VERTICAL,command=my_canvas.yview) y_scrollbar.pack(side=RIGHT,fill=Y) # Configure the canvas my_canvas.configure(xscrollcommand=x_scrollbar.set) my_canvas.configure(yscrollcommand=y_scrollbar.set) my_canvas.bind("<Configure>",lambda e: my_canvas.config(scrollregion= my_canvas.bbox(ALL))) # Create Another Frame INSIDE the Canvas second_frame = Frame(my_canvas) # Add that New Frame a Window In The Canvas my_canvas.create_window((0,0),window= second_frame, anchor="nw") for thing in range(100): Button(second_frame ,text=f"Button {thing}").grid(row=5,column=thing,pady=10,padx=10) for thing in range(100): Button(second_frame ,text=f"Button {thing}").grid(row=thing,column=5,pady=10,padx=10) root.mainloop() 
Sign up to request clarification or add additional context in comments.

Comments

1

you might be able to set a scrollbarr to root.

scrollderoot = tkinter.Scrollbar(orient="vertical", command=root.yview) scrollderoot.grid(column=5, row=0, sticky='ns', in_=root) #instead of number 5, set the column as the expected one for the scrollbar. Sticky ns will might be neccesary. root.configure(yscrollcommand=scrollderoot.set) 

Honestly i didn't tried this but "should" work. Good luck.

1 Comment

You will get the error AttributeError: '_tkinter.tkapp' object has no attribute 'yview', this way you will not be able to get the wanted result.
1

This approach uses no Frame objects and is different in that it creates a very large Canvas with Scrollbars and asks you for an image to display on it.

The screen is then set with self.root.wm_attributes("-fullscreen", 1) and self.root.wm_attributes("-top", 1)

Press the Escape key or Alt-F4 to close.

import tkinter as tk from tkinter import filedialog as fido class BigScreen: def __init__( self ): self.root = tk.Tk() self.root.rowconfigure(0, weight = 1) self.root.columnconfigure(0, weight = 1) w, h = self.root.winfo_screenwidth(), self.root.winfo_screenheight() self.canvas = tk.Canvas(self.root, scrollregion = f"0 0 {w*2} {h*2}") self.canvas.grid(row = 0, column = 0, sticky = tk.NSEW) self.makescroll(self.root, self.canvas ) self.imagename = fido.askopenfilename( title = "Pick Image to View" ) if self.imagename: self.photo = tk.PhotoImage(file = self.imagename).zoom(2, 2) self.window = self.canvas.create_image( ( 0, 0 ), anchor = tk.NW, image = self.photo) self.root.bind("<Escape>", self.closer) self.root.wm_attributes("-fullscreen", 1) self.root.wm_attributes("-top", 1) def makescroll(self, parent, thing): v = tk.Scrollbar(parent, orient = tk.VERTICAL, command = thing.yview) v.grid(row = 0, column = 1, sticky = tk.NS) thing.config(yscrollcommand = v.set) h = tk.Scrollbar(parent, orient = tk.HORIZONTAL, command = thing.xview) h.grid(row = 1, column = 0, sticky = tk.EW) thing.config(xscrollcommand = h.set) def closer(self, ev): self.root.destroy() if __name__ == "__main__": Big = BigScreen() Big.root.mainloop() 

My previous answer went well beyond the question asked so this is a cut-down version more accurately answers the question.

Comments

1

I did try the answer of Akash Shendage which didn't work for me out of the box. But with a few adjustments I got it working.

#!/bin/env python3 from tkinter import ttk import tkinter as tk root = tk.Tk() root.title('Full Window Scrolling X Y Scrollbar Example') root.geometry("1350x400") # Create A Main frame main_frame = tk.Frame(root) main_frame.pack(fill=tk.BOTH,expand=1) # Create Frame for X Scrollbar sec = tk.Frame(main_frame) sec.pack(fill=tk.X,side=tk.BOTTOM) # Create A Canvas my_canvas = tk.Canvas(main_frame) my_canvas.pack(side=tk.LEFT,fill=tk.BOTH,expand=1) # Add A Scrollbars to Canvas x_scrollbar = ttk.Scrollbar(sec,orient=tk.HORIZONTAL,command=my_canvas.xview) x_scrollbar.pack(side=tk.BOTTOM,fill=tk.X) y_scrollbar = ttk.Scrollbar(main_frame,orient=tk.VERTICAL,command=my_canvas.yview) y_scrollbar.pack(side=tk.RIGHT,fill=tk.Y) # Configure the canvas my_canvas.configure(xscrollcommand=x_scrollbar.set) my_canvas.configure(yscrollcommand=y_scrollbar.set) my_canvas.bind("<Configure>",lambda e: my_canvas.config(scrollregion= my_canvas.bbox(tk.ALL))) # Create Another Frame INSIDE the Canvas second_frame = tk.Frame(my_canvas) # Add that New Frame a Window In The Canvas my_canvas.create_window((0,0),window= second_frame, anchor="nw") for thing in range(100): tk.Button(second_frame ,text=f"Button {thing}").grid(row=5,column=thing,pady=10,padx=10) for thing in range(100): tk.Button(second_frame ,text=f"Button {thing}").grid(row=thing,column=5,pady=10,padx=10) root.mainloop() 

Comments

0

Here's a class, and some example usage, that uses the .place method to add a scrollbar for the whole window. You can create a Frame object, and place it at your desired (x, y) coordinates. Then, simply pass your Frame object in place of root in main.frame to create a scrollable window at your desired coordinates.

from tkinter import * class ScrollableFrame: """A scrollable tkinter frame that will fill the whole window""" def __init__ (self, master, width, height, mousescroll=0): self.mousescroll = mousescroll self.master = master self.height = height self.width = width self.main_frame = Frame(self.master) self.main_frame.pack(fill=BOTH, expand=1) self.scrollbar = Scrollbar(self.main_frame, orient=VERTICAL) self.scrollbar.pack(side=RIGHT, fill=Y) self.canvas = Canvas(self.main_frame, yscrollcommand=self.scrollbar.set) self.canvas.pack(expand=True, fill=BOTH) self.scrollbar.config(command=self.canvas.yview) self.canvas.bind( '<Configure>', lambda e: self.canvas.configure(scrollregion=self.canvas.bbox("all")) ) self.frame = Frame(self.canvas, width=self.width, height=self.height) self.frame.pack(expand=True, fill=BOTH) self.canvas.create_window((0,0), window=self.frame, anchor="nw") self.frame.bind("<Enter>", self.entered) self.frame.bind("<Leave>", self.left) def _on_mouse_wheel(self,event): self.canvas.yview_scroll(-1 * int((event.delta / 120)), "units") def entered(self,event): if self.mousescroll: self.canvas.bind_all("<MouseWheel>", self._on_mouse_wheel) def left(self,event): if self.mousescroll: self.canvas.unbind_all("<MouseWheel>") # Example usage obj = ScrollableFrame( master, height=300, # Total required height of canvas width=400 # Total width of master ) objframe = obj.frame # use objframe as the main window to make widget 

Comments

0

From the great effbot docs:

In Tkinter, the scrollbar is a separate widget that can be attached to any widget that support the standard scrollbar interface. Such widgets include:

  • the Listbox widget.
  • the Text widget.
  • the Canvas widget
  • the Entry widget

So, you cannot directly use a scrollbar in a Frame. It may be possible to create your own Frame sub-class that supports the scrollbar interface.

You can use a Canvas to have scrollable content, but placing widgets within a Canvas does not use pack or grid, but uses explicit pixel locations (i.e. painting on the Canvas).

3 Comments

"Out of the 4 widgets listed above, only one allows other widgets within it: the Canvas" - that is not a true statement. You can embed widgets in a text widget.
@BryanOakley Would embedding widgets into a Text widget (instead of Canvas) offer any processing or rendering speed advantage?
@SanguineL: no, I don't think it would have any affect on that.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.