Scrollbars on canvas in tkinter does not work - python

Yes there are many stackoverflow questions regarding this, i saw everything but could not get this working so i am asking a new question with my code:
Basically i want to create a table in tkinter with 4 columns. But i want to be able to scroll this because the rows will be later taken from the mysql database. but i cannot get the scroll working.
Here is my code :
from tkinter import *
root = Tk()
root.geometry("700x600")
frame_canvas = Frame(root)
frame_canvas.rowconfigure(0, weight=1)
frame_canvas.columnconfigure(0, weight=1)
frame_canvas.grid(row=0, column=0, sticky="news")
canvas = Canvas(frame_canvas)
canvas.grid(row=0, column=0, sticky="news")
vsb = Scrollbar(frame_canvas, orient="vertical", command=canvas.yview)
vsb.grid(row=0, column=1, sticky='ns')
canvas.configure(yscrollcommand=vsb.set)
for i in range(0, 50):
for j in range(0, 4):
canvas.columnconfigure(j, minsize=150)
Label(canvas, text="hello"+str(i)+str(j)).grid(row=i, column=j)
canvas.config(scrollregion=canvas.bbox("all"))
app = root
root.mainloop()
How to i get the canvas to scroll ? Is there another way to create a table ? Also later if i want to add a row to the bottom of the table, how is it possible ? or do i have to clear the whole canvas and re-render it or something ?
EDIT
Have added a frame window to the canvas. Still scroll won't work. That could be the issue now ?
from tkinter import *
root = Tk()
root.geometry("700x600")
frame_canvas = Frame(root)
frame_canvas.rowconfigure(0, weight=1)
frame_canvas.columnconfigure(0, weight=1)
frame_canvas.grid(row=0, column=0, sticky="news")
canvas = Canvas(frame_canvas, height=600, width=500)
canvas.grid(row=0, column=0, sticky="news")
vsb = Scrollbar(frame_canvas, command=canvas.yview, orient="vertical")
vsb.grid(row=0, column=1, sticky='ns')
canvas.configure(yscrollcommand=vsb.set)
frame2 = Frame(canvas, bg="powder blue", height=600, width=700)
canvas.create_window((0, 0), anchor="nw", height=600, width=600, window=frame2)
for i in range(0, 50):
for j in range(0, 4):
frame2.columnconfigure(j, minsize=120)
Label(frame2, bg="powder blue", text="hello"+str(i)+str(j)).grid(row=i, column=j)
canvas.config(scrollregion=frame2.bbox("all"))
app = root
root.mainloop()

Related

Scrollable frame in customtkinter with .grid

I want to create a GUI with two frames, one of which must be scrollable. I tried to create a scrollbar using canvas, but following the instructions from several tutorials I came to something strange:
I'm using the .grid method instead of the simple pack, because I want more control over the placement of elements (many in a row). I tried converting these tutorial methods from .pack to .grid, maybe that's why it doesn't work.
import customtkinter
import tkinter
class MyGui:
def __init__(self, app):
self.app = app
self.app.geometry("500x300")
self.app.grid_rowconfigure(0, weight=1)
self.app.grid_columnconfigure((0, 1), weight=1)
self.frame = customtkinter.CTkFrame(self.app)
self.frame.grid(
row=0, column=0, columnspan=3, padx=20, pady=(20, 5), sticky="NSEW"
)
self.canvas = customtkinter.CTkCanvas(self.frame)
self.canvas.grid(row=0, column=0, columnspan=3, sticky="NSEW")
self.scrollbar = customtkinter.CTkScrollbar(
master=self.frame, orientation="vertical", command=self.canvas.yview
)
self.scrollbar.grid(row=0, column=2, sticky="E")
self.canvas.configure(yscrollcommand=self.scrollbar.set)
self.frame_1 = customtkinter.CTkFrame(master=self.canvas)
self.frame_1.grid(
row=0, column=0, columnspan=3, padx=20, pady=(20, 5), sticky="NSEW"
)
self.canvas.create_window((0, 0), window=self.frame_1, anchor="nw")
self.frame_2 = customtkinter.CTkFrame(master=self.app)
self.frame_2.grid(
row=1, column=0, columnspan=3, padx=20, pady=(5, 20), sticky="NSEW"
)
for x in range(100):
customtkinter.CTkButton(self.frame_1, text=f"Button {x}").grid(
row=x, column=0
)
customtkinter.CTkEntry(
master=self.frame_1, placeholder_text=f"Entry {x}"
).grid(row=x, column=1)
customtkinter.CTkEntry(
master=self.frame_1, placeholder_text=f"Entry {x}"
).grid(row=x, column=2)
customtkinter.CTkButton(self.frame_2, text="Lonely button").pack(padx=5, pady=5)
app = customtkinter.CTk()
running = MyGui(app)
app.mainloop()
Also note that beside 'crashed' windows, scrollbar does not change position while scrolling because it takes up all his space and frames does not seem to expanding to fill the window.

why my tkinter scrollbar not working after adding scrollbar?

I have made a user interface but my scrollbar is not working. it is working if i add content statically but when i add frames from button click then it adds new frame but not scrolling to view bottom content or we can say the scroll bar is disabled.
Here is my code:
import tkinter as tk
from tkinter import *
from PIL import ImageTk, Image
root = tk.Tk()
root.grid_rowconfigure(0, weight=1)
root.columnconfigure(0, weight=1)
root.title("Hello Python")
root.configure(bg="#010523")
root.iconbitmap('logo.ico')
root.geometry("400x500")
frame_main = tk.Frame(root, bg="#010523")
frame_main.grid(sticky='news')
# ********************header frame********************************
header_frame = LabelFrame(frame_main, bg="#010523", border=0, height=100)
header_frame.grid(row=0, column=0, columnspan=2, sticky='ew')
width =50
height =50
photo= Image.open("logo.png")
photo= photo.resize((width, height),Image.ANTIALIAS)
# create an object of PhotoImage
photoImg = ImageTk.PhotoImage(photo)
photo_label= Label(header_frame, image=photoImg, bg="#010523")
photo_label.grid(row=0, column=0, rowspan=2)
# Label
public_broadcast = Label(header_frame, text="Public broadcast",
font="bold", bg="#010523", fg="white")
public_broadcast.grid(row=0, column=1)
_id = Label(header_frame, text="MY ID: 0013A20041EFD12C",
font="10", bg="#010523", fg="grey")
_id.grid(row=1, column=1, padx=10)
# ********************end of header frame*************************
# label1 = tk.Label(frame_main, text="Label 1", fg="green")
# label1.grid(row=0, column=0, pady=(5, 0), sticky='nw')
# label2 = tk.Label(frame_main, text="Label 2", fg="blue")
# label2.grid(row=1, column=0, pady=(5, 0), sticky='nw')
# label3 = tk.Label(frame_main, text="Label 3", fg="red")
# label3.grid(row=3, column=0, pady=5, sticky='nw')
# Create a frame for the canvas with non-zero row&column weights
frame_canvas = tk.Frame(frame_main)
frame_canvas.grid(row=2, column=0, pady=(5, 0), sticky='nw')
frame_canvas.grid_rowconfigure(0, weight=1)
frame_canvas.grid_columnconfigure(0, weight=1)
# Set grid_propagate to False to allow 5-by-5 buttons resizing later
frame_canvas.grid_propagate(False)
# Add a canvas in that frame
canvas = tk.Canvas(frame_canvas, bg="yellow")
canvas.grid(row=0, column=0, sticky="news")
# Link a scrollbar to the canvas
vsb = tk.Scrollbar(frame_canvas, orient=VERTICAL, command=canvas.yview)
vsb.grid(row=0, column=1, sticky='ns')
canvas.configure(yscrollcommand=vsb.set)
# Create a frame to contain the buttons
frame_buttons = tk.Frame(canvas, bg="blue")
# Add 9-by-5 buttons to the frame
last_frame_row = 3
frame_canvas.config(width=400, height=300)
# Entering self msg frame with text
def add_msg_frame():
global last_frame_row
msg = "This is a test msg"
# msg = e.get()
# e.delete(0, END)
new_frame = Frame(frame_buttons, bg="#4857a8", borderwidth=0)
new_frame.grid(row=last_frame_row, column=1, columnspan=2, sticky='e', pady=5)
last_frame_row += 1
new_label = Label(new_frame, text=msg, font="10", bg="#4857a8", fg="white")
new_label.grid(row=0, column=0)
canvas.create_window((0, 0), window=frame_buttons, anchor='nw')
def add_reply_msg(device_id="0983ADFCD9827sd", msg="this is a sample message"):
global last_frame_row
new_frame = Frame(frame_buttons, bg="#1f243f", borderwidth=0)
new_frame.grid(row=last_frame_row, column=0, columnspan=2, sticky='w', pady=5)
last_frame_row += 1
new_label = Label(new_frame, text=device_id, bg="#1f243f", font="10", fg="#a6a6a6")
new_label.grid(row=0, column=0)
new_label2 = Label(new_frame, text=msg, font="10", bg="#1f243f", fg="white")
new_label2.grid(row=1, column=0)
# Update buttons frames idle tasks to let tkinter calculate buttons sizes
# for i in range(30):
# add_msg_frame()
add_reply_msg()
add_reply_msg()
add_msg_frame()
frame_buttons.update_idletasks()
# Set the canvas scrolling region
canvas.config(scrollregion=canvas.bbox("all"), yscrollcommand=vsb.set)
canvas.create_window((0, 0), window=frame_buttons, anchor='nw')
canvas.bind('<Configure>', lambda e: canvas.configure(scrollregion=canvas.bbox("all")))
# # Entry
eFrame = Frame(root, width=400, height=100)
eFrame.grid(row=1000, column=0)
e = Entry(eFrame, width=50)
e.grid(row=0, column=0)
ebtn = Button(eFrame, text="Send", bg="skyblue", command=add_msg_frame)
ebtn.grid(row=0, column=1)
# Launch the GUI
root.mainloop()
Please give me suggestions that how can i enable scrollbar when add a frame by clicking the send button.
Thank you.
You need to update the scrollregion whenever you add or modify things on the canvas.
frame_buttons will be resized when items are added to it, so you need to update the scrollregion of the canvas in this case via bind('<Configure>', ...). Also it is better to call canvas.create_window((0, 0), window=frame_buttons, anchor='nw') once outside the function add_msg_frame():
...
# Create a frame to contain the buttons
frame_buttons = tk.Frame(canvas, bg="blue")
# call canvas.create_window(...) once here
canvas.create_window((0, 0), window=frame_buttons, anchor='nw')
# update scrollregion of canvas whenever the frame is resized
frame_buttons.bind('<Configure>', lambda e: canvas.config(scrollregion=canvas.bbox('all')))
...

How can I insert label in a scrollable canvas?

The scroll don't work at all. What's wrong in the code?
I'm using Python 2.7.16
I read that listbox and text widgets are used only for text. As I want to use labels, I'm trying to insert the labels in a frame, but as a Frame didn't scroll I decided to use a canvas. But I couldn't get it to work.
from Tkinter import *
root = Tk()
frame = Frame(root, width=300, height=200)
frame.grid(row=0, column=0)
canvas=Canvas(frame, bg='#FFFFFF', width=300, height=200, scrollregion=(0,0,500,500))
vbar = Scrollbar(frame, orient=VERTICAL)
vbar.pack(side=RIGHT, fill=Y)
canvas.config(width=300, height=250)
canvas.pack(side=LEFT, expand=True, fill=BOTH)
mylist = Frame(canvas, width=100)
for x in range(10):
texto = Label(mylist, text='CODE', bd=2, width=7, relief=RIDGE)
texto.grid(row=x, column=0)
texto1 = Label(mylist, text='EQUIPAMENT', bd=2, width=20, relief=RIDGE)
texto1.grid(row=x, column=1)
mylist.place(x=0, y=0)
vbar.config(command=canvas.yview)
canvas.config(yscrollcommand=vbar.set)
mainloop()

Changing the size of a scrollbar in tkinter(using grid layout)

I'm making a Tkinter GUI that allows you to query a database and will display results in a scrollable frame. However, when you produce the results the scrollbar will not adjust to match the new size of the frame. How can I get the scrollbar to be able to display all of the results? I've put together a quick and dirty version of the code to demonstrate the problem I'm having.
import tkinter as tk
def Lookup():
list = frame_buttons.grid_slaves()
for l in list:
l.destroy()
for x in range(1000):
tk.Label(frame_buttons, text="test", background="white").grid(row=x)
root = tk.Tk()
root.grid_rowconfigure(0, weight=1)
root.columnconfigure(0, weight=1)
frame_main = tk.Frame(root, bg="white")
frame_main.grid(row = 0,sticky='news')
frame_input = tk.Frame(frame_main, background = "white")
frame_input.grid(row=0, column=0, pady=(5, 0), sticky='nw')
tk.Button(frame_input, text="Search", fg="black", background = "grey",command=Lookup).grid(row=3, column=0,sticky='nw')
# Create a frame for the canvas with non-zero row&column weights
frame_canvas = tk.Frame(frame_main)
frame_canvas.grid(row=1, column=0, pady=(5, 0), sticky='nw')
frame_canvas.grid_rowconfigure(0, weight=1)
frame_canvas.grid_columnconfigure(0, weight=1)
# Set grid_propagate to False to allow 5-by-5 buttons resizing later
frame_canvas.grid_propagate(False)
# Add a canvas in that frame
canvas = tk.Canvas(frame_canvas, bg="gray")
canvas.grid(row=0, column=0, sticky="news")
# Link a scrollbar to the canvas
vsb = tk.Scrollbar(frame_canvas, orient="vertical", command=canvas.yview)
vsb.grid(row=0, column=1, sticky='ns')
canvas.configure(yscrollcommand=vsb.set)
frame_buttons = tk.Frame(canvas, bg="gray")
canvas.create_window((0, 0), window=frame_buttons, anchor='nw')
for x in range(15):
tk.Label(frame_buttons, text="blah", background = "white").grid(row=x)
frame_buttons.update_idletasks()
frame_canvas.config(width=500, height=100)
canvas.config(scrollregion=canvas.bbox("all"))
root.mainloop()
this initially puts 20 labels in the scroll region, which is enough to activate the scrollbar. Then when you click search it replaces those 20 lables with 1000 test labels. But only the first 20 will be viewable.
You need to reset the scrollregion whenever the frame changes size and the items are redrawn.
The normal way to do that is to bind to the <Configure> event of the frame so that it happens automatically as the frame grows and shrinks.
Example:
def reset_scrollregion(event):
canvas.config(scrollregion=canvas.bbox("all"))
...
frame_buttons.bind("<Configure>", reset_scrollregion)

Scrollbars for a .jpg image on a Tkinter Canvas in Python

I'm trying to make a jpeg on a canvas scrollable but I can't seem to get my scrollbars to work. Here's some example code:
from Tkinter import *
import Image, ImageTk
root = Tk()
frame = Frame(root, bd=2, relief=SUNKEN)
frame.grid_rowconfigure(0, weight=1)
frame.grid_columnconfigure(0, weight=1)
xscrollbar = Scrollbar(frame, orient=HORIZONTAL)
xscrollbar.grid(row=1, column=0, sticky=E+W)
yscrollbar = Scrollbar(frame)
yscrollbar.grid(row=0, column=1, sticky=N+S)
canvas = Canvas(frame, bd=0, xscrollcommand=xscrollbar.set, yscrollcommand=yscrollbar.set)
canvas.grid(row=0, column=0, sticky=N+S+E+W)
File = "jpg filepath here"
img = ImageTk.PhotoImage(Image.open(File))
canvas.create_image(0,0,image=img, anchor="nw")
xscrollbar.config(command=canvas.xview)
yscrollbar.config(command=canvas.yview)
frame.pack()
root.mainloop()
You need to tell the canvas what part of the drawing space to scroll. Use something like:
canvas.config(scrollregion=canvas.bbox(ALL))
More information can be found here: http://effbot.org/tkinterbook/canvas.htm#coordinate-systems

Categories

Resources