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"))
Related
I want to fit this frame with scrollbar(refer the provided image) in the black space present in the provided image. How do I do that. The frame should totally cover the black space.
The code for program.The image
from tkinter import *
from tkinter import ttk
C = Tk()
C.maxsize(1200, 750)
C.geometry("1200x750")
C.title("Mainscreen")
style = ttk.Style()
style.theme_use('clam')
BG = PhotoImage(file="Mainscreen bg.png")
ML = PhotoImage(file="Music_label.png")
BG_label = Label(C, image=BG, border=0)
BG_label.place(x=0, y=0)
style.configure("Vertical.TScrollbar", gripcount=0,
background="Cyan", darkcolor="gray6", lightcolor="LightGreen",
troughcolor="Turquoise4", bordercolor="gray6", arrowcolor="gray6",arrowsize=15)
wrapper1= LabelFrame(C, width="1600", height="100", background="gray6",bd=0)
mycanvas = Canvas(wrapper1,background="gray6",borderwidth=0, highlightthickness=0, width=700, height=600)
mycanvas.pack(side=LEFT, expand="false", padx=0)
yscrollbar = ttk.Scrollbar(wrapper1, orient="vertical",command=mycanvas.yview)
yscrollbar.pack(side=RIGHT, fill="y")
mycanvas.configure(yscrollcommand=yscrollbar.set)
mycanvas.bind('<Configure>',lambda e: mycanvas.configure(scrollregion=mycanvas.bbox("all")))
myframe = Frame(mycanvas)
mycanvas.create_window((0,0), window=myframe, anchor="n")
wrapper1.pack(side=RIGHT,expand="false", padx=0, pady=200)
for i in range(50):
Button(myframe, image=ML,bg="gray6",bd=0).pack()
mainloop()
EDIT:
Music_Label
Mainscreen bg
So after trying to understand the underlying problem for a while I have reached the conclusion, that the problem is with the fact that the button are being drawn in the myframe and the myframe is outside the mycanvas which contains the scrollbar. So by changing the master widget for the button from myframe to mycanvas, the problem gets fixed now the scrollbar is adjacent to the buttons. BUT, Also now the button r shifted the side since while packing the wrapper1, you did side = RIGHT, so I would also suggest that you use place here instead of pack, since pack depends on the space available and is not reliable if you are using a Background for your GUI and want the buttons within a portion of it.
I have changed the following lines -:
Button(mycanvas, image=ML,bg="gray6",bd=0).pack() # Changed to mycanvas from myframe
and
wrapper1.place(x = {YOUR X, WHERE THE BOX STARTS}, y = {YOUR Y, WHERE THE BOX STARTS}) # Use place instead..
You can use pack also, and change the padx and pady arguments but it will be tricky to get it to work always as expected.
The fixed code is this -:
from tkinter import *
from tkinter import ttk
C = Tk()
C.maxsize(1200, 750)
C.geometry("1200x750")
C.title("Mainscreen")
style = ttk.Style()
style.theme_use('clam')
BG = PhotoImage(file="Mainscreen bg.png")
ML = PhotoImage(file="Music_label.png")
BG_label = Label(C, image=BG, border=0)
BG_label.place(x=0, y=0)
style.configure("Vertical.TScrollbar", gripcount=0,
background="Cyan", darkcolor="gray6", lightcolor="LightGreen",
troughcolor="Turquoise4", bordercolor="gray6", arrowcolor="gray6",arrowsize=15)
wrapper1= LabelFrame(C, width="1600", height="100", background="gray6",bd=0)
mycanvas = Canvas(wrapper1,background="gray6",borderwidth=0, highlightthickness=0, width=700, height=600)
mycanvas.pack(side=LEFT, expand=False, padx=0)
yscrollbar = ttk.Scrollbar(wrapper1, orient="vertical",command=mycanvas.yview)
yscrollbar.pack(side=RIGHT, fill="y", expand = False)
mycanvas.configure(yscrollcommand=yscrollbar.set)
mycanvas.bind('<Configure>',lambda e: mycanvas.configure(scrollregion=mycanvas.bbox("all")))
myframe = Frame(mycanvas)
mycanvas.create_window((0,0), window=myframe, anchor="n")
wrapper1.pack(expand=True, padx=0, pady=200) # Use place instead
for i in range(50):
Button(mycanvas, image=ML,bg="gray6",bd=0).pack() # Change this to mycanvas from myframe
mainloop()
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.
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()
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. :)
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()