简体   繁体   中英

Python Tkinter Scrollbar for entire window

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()

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.

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.

Out of the 4 widgets listed above, only one allows other widgets within it: the Canvas. 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 (ie painting on the Canvas).

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()

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 inplace 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

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 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.

I did try the answer of Akash Shendage which didn't work for me out of the box. But with a few adjustments go 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()

I applied codecAkash Shendage to my project but it doesn't work.I have 100s label and these label I use place method Is this due to place method instead of grid

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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM