Vertical scrollbar for frame in Tkinter, Python - python

My aim is to have a scrollbar that stays at the right-side of a full-screen window, allowing the user to scroll up and down through various different widgets (such as labels & buttons).
From other answers I've seen on this site, I've come to the conclusion that a scrollbar has to be assigned to a canvas in order for it to function properly, which I have tried to include in my code but have not had much success with.
The below code shows a simplified version of what I've managed to accomplish so far:
from tkinter import *
root = Tk()
root.state("zoomed")
root.title("Vertical Scrollbar")
frame = Frame(root)
canvas = Canvas(frame)
Label(canvas, text = "Test text 1\nTest text 2\nTest text 3\nTest text 4\nTest text 5\nTest text 6\nTest text 7\nTest text 8\nTest text 9", font = "-size 100").pack()
scrollbar = Scrollbar(frame)
scrollbar.pack(side = RIGHT, fill = Y)
canvas.configure(yscrollcommand = scrollbar.set)
canvas.pack()
frame.pack()
root.mainloop()
I'm facing two issues when running this code:
One is that the scrollbar is inactive, and doesn't allow for the user to scroll down to view the rest of the text.
The other is that the scrollbar is attached to the right-side of the text, rather than the right-side of the window.
So far, none of the other answers I've found on this site have enabled me to amend my code to support a fully-functioning scrollbar for my program. I'd be very grateful for any help anyone reading this could provide.

See again link: https://stackoverflow.com/a/3092341/7432
It shows how to create scrolled frame - and then you can add all widgets in this frame.
import tkinter as tk
def on_configure(event):
# update scrollregion after starting 'mainloop'
# when all widgets are in canvas
canvas.configure(scrollregion=canvas.bbox('all'))
root = tk.Tk()
# --- create canvas with scrollbar ---
canvas = tk.Canvas(root)
canvas.pack(side=tk.LEFT)
scrollbar = tk.Scrollbar(root, command=canvas.yview)
scrollbar.pack(side=tk.LEFT, fill='y')
canvas.configure(yscrollcommand = scrollbar.set)
# update scrollregion after starting 'mainloop'
# when all widgets are in canvas
canvas.bind('<Configure>', on_configure)
# --- put frame in canvas ---
frame = tk.Frame(canvas)
canvas.create_window((0,0), window=frame, anchor='nw')
# --- add widgets in frame ---
l = tk.Label(frame, text="Hello", font="-size 50")
l.pack()
l = tk.Label(frame, text="World", font="-size 50")
l.pack()
l = tk.Label(frame, text="Test text 1\nTest text 2\nTest text 3\nTest text 4\nTest text 5\nTest text 6\nTest text 7\nTest text 8\nTest text 9", font="-size 20")
l.pack()
# --- start program ---
root.mainloop()

I would recommend using tkScrolledFrame
https://pypi.org/project/tkScrolledFrame/
They have a great little example on the website too. So easy to use and works great for me.
Below is a quick example:
from tkscrolledframe import ScrolledFrame
import tkinter as tk
# Create a root window
root = tk.Tk()
frame_top = tk.Frame(root, width=400, height=250)
frame_top.pack(side="top", expand=1, fill="both")
# Create a ScrolledFrame widget
sf = ScrolledFrame(frame_top, width=380, height=240)
sf.pack(side="top", expand=1, fill="both")
# Bind the arrow keys and scroll wheel
sf.bind_arrow_keys(frame_top)
sf.bind_scroll_wheel(frame_top)
frame = sf.display_widget(tk.Frame)
l = tk.Label(frame, text="Test text 1\nTest text 2\nTest text 3\nTest text 4\nTest text 5\nTest text 6\nTest text 7\nTest text 8\nTest text 9", font="-size 20")
l.pack()
root.mainloop()

Related

Python Tkinter how can I place background text in a textbox?

I am trying to place a greyed out background text inside a textbox, that disappears when someone begins to type. I have tried overlaying a label onto the textbox, but I could not get it to work. Here is some code I am running for the text box
root = tk.Tk()
S = tk.Scrollbar(root)
T = tk.Text(root, height=70, width=50)
S.pack(side=tk.RIGHT, fill=tk.Y)
T.pack(side=tk.LEFT, fill=tk.Y)
S.config(command=T.yview)
T.config(yscrollcommand=S.set)
root.protocol("WM_DELETE_WINDOW", stop)
tk.mainloop()
How can I put in the background text?
Using a callback function you can remove the default text and change the foreground colour
import tkinter as tk
root = tk.Tk()
e = tk.Entry(root, fg='grey')
e.insert(0, "some text")
def some_callback(event): # must include event
e.delete(0, "end")
e['foreground'] = 'black'
# e.unbind("<Button-1>")
e.unbind("<FocusIn>")
return None
# e.bind("<Button-1>", some_callback)
e.bind("<FocusIn>", some_callback)
e.pack()
root.mainloop()
You are probably talking about placeholders , tkinter does not have placeholder attribute for Text widget, but you do something similar with Entry widget . You have to do it manually, by binding an event with the Text widget.
text = tk.StringVar()
text.set('Placeholder text')
T = tk.Entry(root, height=70, width=50, textvariable = text)
def erasePlaceholder(event):
if text.get() == 'Placeholder text':
text.set('')
T.bind('<Button-1>', erasePlaceholder)
Try to ask if you face any issues.

Tkinter: cannot use geometry manager grid inside .!frame2 which already has slaves managed by pack

This is my first time using tkinter and I already did some research on pack and grid. How do I fix this code so that the pack and grid components don't intertwine?
I want to use grid for my checkbox so that 16 checkboxes show up in a column next to the words corresponding to them. Can I do this with pack?
# tkinter will help us with the GUI
import tkinter as tk
from tkinter import filedialog, Text
import os
def data():
categoriesArray = ["16 words here"]
for i in range(16):
checkbox = tk.Checkbutton(buttonFrame, bg="white")
checkbox.grid(row=i, column=0, sticky="w")
tk.Label(canvasFrame, text=categoriesArray[i]).grid(row=i, column=1, sticky="ew")
# Define the scrolling function for the scrollbar
def scrollFunction(event):
canvas.configure(scrollregion=canvas.bbox("all"), width=200, height=500)
# The root holds the whole app structure. Always attach to root.
root = tk.Tk()
# These two lines literally make the rectangular structure of the app.
canvas = tk.Canvas(root, height = 500, width= 1300, bg="#00008B")
canvas.pack()
# These two lines make the white screen you see on the left of the buttons.
frame = tk.Frame(root, bg="white")
frame.place(relwidth=0.8, relheight=0.8, relx=0.03, rely=0.1)
# This is the frame for the buttons on the right
buttonFrame = tk.Frame(root, bg="white")
buttonFrame.place(relwidth=0.13, relheight=0.8, relx=0.85, rely=0.1)
# You need a canvas to define a scrollbar within the app.
# Resource: https://stackoverflow.com/questions/16188420/tkinter-scrollbar-for-frame
canvas=tk.Canvas(buttonFrame)
canvasFrame=tk.Frame(canvas)
scrollbar=tk.Scrollbar(buttonFrame, orient="vertical", command=canvas.yview)
canvas.configure(yscrollcommand=scrollbar.set)
scrollbar.pack(side="right", fill="y")
canvas.pack(side="left")
canvas.create_window((36,0), window=canvasFrame, anchor='nw')
canvasFrame.bind("<Configure>", scrollFunction)
# Call the data for the categories to show on the right
data()
# This runs the mainframe to work
root.mainloop()
Please let me know anything I can do to make my question better.
Places I've looked but gotten confused: fix this code 'cannot use geometry manager grid inside . which already has slaves managed by pack'
I fixed it. checkbox = tk.Checkbutton(buttonFrame, bg="white") should have canvasFrame instead of buttonFrame.

Tkinter. Scrollbar is not working on Canvas

I am newbie in programming, don't hate me pls :)
Why scroll is not working on my canvas widget?
I added loop with 30 rows and I cannot scroll down.
Its look like it because of create_text() method or maybe not.
I've written code for example below.
from tkinter import *
root = Tk()
root.geometry('200x150')
frame = Frame(root)
yscrollbar = Scrollbar(frame, orient=VERTICAL)
yscrollbar.pack(fill=Y, side=RIGHT)
canvas = Canvas(frame,
yscrollcommand=yscrollbar.set,
bg='white')
canvas.pack(fill=BOTH)
yscrollbar.config(command=canvas.yview)
n=12
for i in range(1,31):
canvas.create_text(10,n,text=i)
n+=12
frame.pack()
root.mainloop()
Scrolling is not responsive because you need to tell the canvas to limit the scrolling to a given area.
You can use the bbox method to get a bounding box for a given object, or a group of objects.
canvas.bbox(ALL) returns the bounding box for all objects on the canvas.
Link: http://effbot.org/zone/tkinter-scrollbar-patterns.htm you can check other methods to do this in this link
Here is the working code:
from tkinter import *
root = Tk()
root.geometry('200x150')
frame = Frame(root)
yscrollbar = Scrollbar(frame, orient=VERTICAL)
yscrollbar.pack(fill=Y, side=RIGHT)
canvas = Canvas(frame,
yscrollcommand=yscrollbar.set,
bg='white')
canvas.pack(fill=BOTH)
yscrollbar.config(command=canvas.yview)
n=12
for i in range(1,31):
canvas.create_text(10,n,text=i)
n+=12
frame.pack()
# Add this line to tell the canvas the area over to scroll
canvas.config(scrollregion=canvas.bbox(ALL))
root.mainloop()

Tkinter Canvas Scrollbars stopped working

Intitially when the frame and canvas size were smaller both scrollbars worked fine. After I increased their size to match that of the Toplevel, the x scrollbar disappear and the y one stopped working.
You may say I don't need the x scrollbar, because I adjusted the canvas create_text width attribute to fit the text within the window, and you'd be right, but I am trying to learn how to use scrollbars when the window's maximize button is on and when it's off.
The files I load to read are pretty lengthy, so I need the y scrollbar to scroll all the way to the end of the text. Checking some online notes on the scrollregion, I came a cross one that suggested using n,e,w,s coordintates, but when I use them, I get errores. I used scrollregion=(0,0,500,500) but that seems too finite to me.
from tkinter import *
from tkinter import font
newline=''
fileContent=[]
filePath='file.txt'
lines=open(filePath)
newline=lines.read()
w=Tk()
def openViewer():
pop = Toplevel(w)
pop.title('Operation Report')
pop.geometry("750x500+15+20")
pop.state('zoomed') # Window's Miximize button
frame=Frame(pop,width=780,height=560)
frame.grid(row=0,column=0)
canvas=Canvas(frame, width=780, height=560, background='black')
canvas.config(scrollregion=(0,0,500,500))
canvas.pack(side=LEFT, fill=BOTH)
verdana_font = font.Font(family = "Verdana",size = 13)
canvas.create_text((30, 0), anchor='nw', text=newline,
font=verdana_font, fill = 'light grey',
justify=LEFT, width=750)
hbar=Scrollbar(frame,orient=HORIZONTAL)
hbar.pack(side=BOTTOM,fill=X)
hbar.config(command=canvas.xview)
vbar=Scrollbar(frame,orient=VERTICAL)
vbar.pack(side=RIGHT,fill=Y)
vbar.config(command=canvas.yview)
canvas.config(xscrollcommand=hbar.set, yscrollcommand=vbar.set)
btn=Button(w, text='View Content', command=openViewer)
btn.pack()
w.mainloop()
from tkinter import *
from tkinter import font
newline=''
fileContent=[]
filePath='C:/path to/ file.txt'
lines=open(filePath)
newline=lines.read()
w=Tk()
def openViewer():
pop = Toplevel(w)
pop.title('Operation Report')
pop.geometry("750x500+15+20")
pop.state('zoomed') # Window's Miximize button
frame=Frame(pop,width=780,height=560)
frame.grid(row=0,column=0)
# I decreased the canvas height to show the x scrollbar and removed
# the create_text method width attribute to unwrap the text and
# activate the horizontal scrollbar
canvas=Canvas(frame, width=780,height=530, background='black')
verdana_font = font.Font(family = "Verdana",size = 13)
canvas.create_text((0, 0), anchor='nw', text=newline,
font=verdana_font, fill = 'light grey',
justify=LEFT) # Add this width=750 to wrap text
hbar=Scrollbar(frame,orient=HORIZONTAL)
hbar.pack(side=BOTTOM,fill=X)
hbar.config(command=canvas.xview)
vbar=Scrollbar(frame,orient=VERTICAL)
vbar.pack(side=RIGHT,fill=Y)
vbar.config(command=canvas.yview)
canvas.config(scrollregion=canvas.bbox(ALL))
canvas.config(xscrollcommand=hbar.set, yscrollcommand=vbar.set)
canvas.pack(side=LEFT, expand=True, fill=BOTH)
btn=Button(w, text='View Content', command=openViewer)
btn.pack()
w.mainloop()
Hopefully, this may help someone else with the same or similar problem. :)

Make scrollbar change length dynamically on Canvas tkinter

I've created a program in Python where i request some HTML through an urllib2 call and I print it on a Canvas item.
HTML source code is quite long so I tried to add a scrollbar to my canvas, but this one doesn't appear when the text is printed
Is there a way to make Scrollbar change dimension dinamically detecting the text lenght? Thank you in advance
This is my source code:
from tkinter import *
import urllib.request
def getURL():
canvas.delete("all")
with urllib.request.urlopen(entry.get()) as response:
received_html = response.read()
print(received_html)
canvas.create_text(10,0,text=received_html, anchor=NW, width=700)
#Widget and item initialization
browser_window = Tk()
browser_window.geometry('900x700') # Size 900, 700
frame = Frame(browser_window) #frame
frame.pack(side=TOP, fill=BOTH, expand=5)
label = Label(frame, text= 'Inserisci URL:')
entry = Entry(frame)
canvas = Canvas(frame) #canvas
scrollbar = Scrollbar(frame, orient=VERTICAL, command=canvas.yview)
#Scrollbar on my canvas
entry.insert(END, "http://jesolo.it")
#canvas configure
canvas.configure(yscrollcommand=scrollbar.set, background='#ffffff',
scrollregion=canvas.bbox("all"))
button = Button(frame, text='Vai', command=getURL )
label.pack(side=TOP)
entry.pack(side=TOP)
button.pack(side=TOP)
scrollbar.pack(side=RIGHT, fill=Y) #Scrollbar pack
canvas.pack(side=LEFT, fill=BOTH, expand=5) #Canvas config
scrollbar.config(command=canvas.yview)
browser_window.mainloop()
Once you add the text to the canvas, you need to update the scrollregion attribute so that the canvas knows how much of its virtual space should be scrollable.
def getURL():
...
canvas.create_text(10,0,text=received_html, anchor=NW, width=700)
canvas.configure(scrollregion=canvas.bbox("all"))

Categories