This is my code:
import tkinter as tk
from tkinter import ttk
root = tk.Tk()
root.protocol("WM_DELETE_WINDOW", lambda: on_closing(root, btn))
frame1 = tk.Frame(root, bg=root['background'])
frame1.pack(expand="YES")
canvas = tk.Canvas(frame1, width=200, height=300, relief="sunken", bd=0, bg=root['background'])
scroll_y = tk.Scrollbar(frame1, orient="vertical", command=canvas.yview, bg=canvas['background'])
scroll_y.pack(side="right", fill='y')
canvas.pack(side="top", expand='YES', fill='both')
canvas.configure(yscrollcommand=scroll_y.set)
# canvas.update_idletasks()
# canvas.yview_moveto('1.0')
s = ttk.Style()
s.configure("new.TFrame", background=canvas['background'], width=canvas.winfo_width(), height=canvas.winfo_height())
msgFrame = ttk.Frame(canvas, style="new.TFrame")
msgFrame.bind("<Configure>", lambda e: canvas.configure(scrollregion=canvas.bbox("all")))
canvas.create_window((0, 0), window=msgFrame, anchor="nw")
Why won't the frame change its color? Or its width/height?
If you'd like to put some strings in the frame:
for i in range (50):
lbl = tk.Label(msgFrame, text="example").pack()
First using same background color for all the widgets is hard to see the effect. For debug purpose, use different background colors for different widgets.
Second you cannot set the width and height of a ttk::Frame using style.configure(), specify them in ttk::Frame(...).
Below is an modified example based on your code:
import tkinter as tk
from tkinter import ttk
def on_closing(root):
root.destroy()
root = tk.Tk()
root.geometry("400x400")
root.config(bg="cyan")
root.protocol("WM_DELETE_WINDOW", lambda: on_closing(root))
frame1 = tk.Frame(root, bg="red")
frame1.pack(expand="YES")
canvas = tk.Canvas(frame1, width=200, height=300, relief="sunken", bd=0, bg="green")
scroll_y = tk.Scrollbar(frame1, orient="vertical", command=canvas.yview, bg=canvas['background'])
scroll_y.pack(side="right", fill='y')
canvas.pack(side="top", expand='YES', fill='both')
canvas.configure(yscrollcommand=scroll_y.set)
s = ttk.Style()
s.configure("new.TFrame", background="blue")
msgFrame = ttk.Frame(canvas, style="new.TFrame", width=100, height=200) # set width and height
msgFrame.bind("<Configure>", lambda e: canvas.configure(scrollregion=canvas.bbox("all")))
canvas.create_window((0, 0), window=msgFrame, anchor="nw")
root.mainloop()
And the output:
Related
I have working horizontal scrollbar, but for some reason it does not rezise the "visible" bar. It does scroll perfectly, but I even didin't notice there was a bar before I added style clam.
Here is my code:
from tkinter import *
from tkinter import ttk
root = Tk()
style = ttk.Style()
style.theme_use('clam')
main_frame = Frame(root)
main_frame.pack(fill=BOTH, expand=1)
my_canvas = Canvas(main_frame)
my_canvas.pack(side=TOP, fill=BOTH, expand=1)
my_scrollbar = ttk.Scrollbar(main_frame, orient=HORIZONTAL, command=my_canvas.xview)
my_scrollbar.pack(side=BOTTOM, fill=X)
my_canvas.configure(yscrollcommand=my_scrollbar.set)
my_canvas.bind('<Configure>', lambda e: my_canvas.configure(scrollregion=my_canvas.bbox("all")))
seccond_frame = Frame(my_canvas)
my_canvas.create_window((0,0), window=seccond_frame, anchor="nw")
for i in range(100):
Label(seccond_frame, text=f"a{i}").grid(row=0, column=i)
root.update()
root.mainloop()
There are two issues in your code:
my_canvas.configure(yscrollcommand=my_scrollbar.set) should be my_canvas.configure(xscrollcommand=my_scrollbar.set)
when adding items to seccond_frame, it is seccond_frame get resized, not my_canvas. So you need to bind <Configure> on seccond_frame instead of my_canvas
i've the problem for make an GUI apps with python tkinter.
here is my sample code
import tkinter as tk
from tkinter import ttk
root = tk.Tk()
root.geometry('300x300')
root.title('CSV Editor')
notebook = ttk.Notebook(root)
notebook.pack(pady=10, expand=True)
tab_home = ttk.Frame(notebook, width=300, height=300)
notebook.add(tab_home, text='Home')
fr_home = tk.Frame(tab_home, background="white")
fr_home.grid(row=0, column=0)
fr_home_container_canvas = tk.Frame(fr_home, background="red")
fr_home_container_canvas.grid(row=0, column=0, sticky='nw')
fr_home_container_canvas.grid_rowconfigure(0, weight=1)
fr_home_container_canvas.grid_columnconfigure(0, weight=1)
fr_home_container_canvas.grid_propagate(False)
canvas_home = tk.Canvas(fr_home_container_canvas)
canvas_home.grid(row=0, column=0, sticky="news")
vsb = tk.Scrollbar(fr_home_container_canvas, orient="vertical", command=canvas_home.yview)
vsb.grid(row=0, column=1, sticky='ns')
canvas_home.configure(yscrollcommand=vsb.set)
fr_home_widget_canvas = tk.Frame(canvas_home, background="yellow")
canvas_home.create_window((0, 0), window=fr_home_widget_canvas, anchor='nw')
fr_home_widget_canvas.config(width=300, height=300, padx=10)
fr_home_container_canvas.config(width=300, height=300)
canvas_home.config(scrollregion=canvas_home.bbox("all"))
text_widget = tk.Text(fr_home_widget_canvas, width = 30, height = 10)
text_widget.grid(column=0, row=0)
root.mainloop()
if i run this code, this is the preview
enter image description here
but when i click inside the text widget, in the frame appear line / border like this
enter image description here
What is that line / border? how to remove it?
thank you so much :)
It is the highlight background which can be removed by setting highlightthickness=0:
canvas_home = tk.Canvas(fr_home_container_canvas, highlightthickness=0)
I created a main root with two frames.
One frame is for program toolbar.
The other frame is for a canvas where data will be displayed and for a scrollbar widget.
Inside of the canvas is a third smaller frame which will be used for scrolling trough data.
However, when I try to define new widgets inside of a function call, the scroll button loses its functionality. That smaller frame is scrollable only if I define these widgets in the top level of the code.
I used a simple for loop to create labels just for testing.
Could anyone tell what I am doing wrong?
from tkinter import *
from tkinter import ttk
#Creating main window
root = Tk()
root.resizable(width=False, height=False)
#Defining Background
toolbar = Frame(root, width=613, height=114)
toolbar.grid(row=0, column=0)
background_frame = Frame(root, width=615, height=560)
background_frame.grid(row=1, column=0)
background = Canvas(background_frame, width=615, height=560)
background.pack(side=LEFT, fill=BOTH, expand=1)
scroll_bar = ttk.Scrollbar(background_frame, orient=VERTICAL, command=background.yview)
scroll_bar.pack(side=RIGHT, fill=Y)
background.configure(yscrollcommand=scroll_bar.set)
background.bind('<Configure>', lambda e:background.configure(scrollregion = background.bbox('all')))
second_frame = Frame(background)
background.create_window(150,100, window=second_frame, anchor='nw')
def confirm1():
for x in range(100):
Label(second_frame, text = x ).grid(row=x, column=1)
show_labels = Button(toolbar, text= "Show labels", fg="black", command=confirm1)
show_labels.grid(row=0, column=2)
root.mainloop()
You need to to update the background canvas' scrollregion whenever you add widgets to the second_frame. That's easy to do by binding to that frame's <Configure> event.
Here's a complete version of your code with a couple of lines added (# WHERE INDICATED) to do that:
from tkinter import *
from tkinter import ttk
#Creating main window
root = Tk()
root.resizable(width=False, height=False)
#Defining Background
toolbar = Frame(root, width=613, height=114)
toolbar.grid(row=0, column=0)
background_frame = Frame(root, width=615, height=560)
background_frame.grid(row=1, column=0)
background = Canvas(background_frame, width=615, height=560)
background.pack(side=LEFT, fill=BOTH, expand=1)
scroll_bar = ttk.Scrollbar(background_frame, orient=VERTICAL, command=background.yview)
scroll_bar.pack(side=RIGHT, fill=Y)
background.configure(yscrollcommand=scroll_bar.set)
# NOT NEEDED
#background.bind('<Configure>',
# lambda e: background.configure(scrollregion=background.bbox('all')))
second_frame = Frame(background)
background.create_window(150,100, window=second_frame, anchor='nw')
# ADDED
second_frame.bind('<Configure>',
lambda e: background.configure(scrollregion=background.bbox('all')))
def confirm1():
for x in range(100):
Label(second_frame, text=x).grid(row=x, column=1)
show_labels = Button(toolbar, text="Show labels", fg="black", command=confirm1)
show_labels.grid(row=0, column=2)
root.mainloop()
Result after clicking button and scrolling the canvas region:
The idea of this python program is to scrape recipes from a food website and output the recipes in a tkinter GUI when clicking the button. I have already applied the scrollbar to the GUI but it is not working as it should. I have already tried many ways but I did not succeed so I decided to ask help from the stack overflow community. I am new to tkinter so sorry for asking help for possibly a silly problem.
The code so far:
import tkinter as tk
from tkinter import Scrollbar
root = tk.Tk()
root.title('Italian-recipes')
height=600
width=895
canvas = tk.Canvas(root, height=height, width=width)
canvas.pack()
background_image = tk.PhotoImage(file='food.png')
background_label = tk.Label(root, image=background_image)
background_label.place(relwidth=1, relheight=1)
lower_frame = tk.Frame(root, bg='#80c1ff', bd=5)
lower_frame.place(relx=0.5, rely=0.25, relwidth=0.75, relheight=0.6, anchor='n')
frame = tk.Frame(root, bg='#AFF9A9', bd=5)
frame.place(relwidth=0.75, relheight=0.1, relx=0.5, rely=0.1, anchor='n')
button = tk.Button(frame, text='Enter food or ingredient', font=40, command=lambda:
test_function(entry.get()))
button.place(relx=0.55, relwidth=0.45, relheight=1)
entry = tk.Entry(frame, font=40)
entry.place(relwidth=0.5, relheight=1)
listbox = tk.Listbox(lower_frame, justify='left', bd=4)
listbox.place(relwidth=1, relheight=1)
label = tk.Label(listbox, anchor='nw', justify='left', bd=4)
label.place(relwidth=1, relheight=1)
scrollbar = Scrollbar(listbox, orient="vertical")
scrollbar.pack( side = 'right', fill = 'y' )
root.mainloop()
I did it with a textfield, that you can see how it work. Change it back to your listbox
import tkinter as tk
from tkinter import Scrollbar
root = tk.Tk()
root.title('Italian-recipes')
height=600
width=895
canvas = tk.Canvas(root, height=height, width=width)
canvas.pack()
lower_frame = tk.Frame(root, bg='#80c1ff', bd=5)
lower_frame.place(relx=0.5, rely=0.25, relwidth=0.75, relheight=0.6, anchor='n')
frame = tk.Frame(root, bg='#AFF9A9', bd=5)
frame.place(relwidth=0.75, relheight=0.1, relx=0.5, rely=0.1, anchor='n')
scrollbar = Scrollbar(lower_frame, orient="vertical")
scrollbar.pack( side = 'right', fill = 'y' )
listbox = tk.Text(lower_frame, yscrollcommand=scrollbar.set, bd=4)
listbox.pack(fill="both", expand="yes")
scrollbar.configure(command=listbox.yview)
root.mainloop()
Can anybody please tell me what I am doing wrong? The scrollbar seems not to reflect the area of the widget it is bound to.
Many thanks.
from tkinter import *
import tkinter as tk
#panel1
root = tk.Tk()
frame1 = tk.Frame(master=root, width=900, height=800)
canvas = tk.Canvas(frame1, width=900, height= 900)
vsb = tk.Scrollbar(frame1, orient=VERTICAL)
canvas.configure(yscrollcommand=vsb.set,
scrollregion=canvas.bbox("all"))
vsb.configure(command=canvas.yview)
canvas.pack(side=LEFT, fill=BOTH, expand=TRUE)
vsb.pack(fill=Y, side=RIGHT, expand=FALSE)
# notebook.add(frame1, text="1")
frame1.pack(expand=True, fill=BOTH)
root.mainloop()
If canvas is empty then there is nothing to scroll. And scrollbar reflects it correctly.
You have to add something to Canvas to scroll it.
I put two Frames bigger than window's size and now you have somthing to scroll.
You have to use scrollregion= after you put items in canvas. Or you can use after() to use scrollregion= after tkinter shows window.
import tkinter as tk
#def resize():
# canvas.configure(scrollregion=canvas.bbox("all"))
root = tk.Tk()
frame1 = tk.Frame(root, width=900, height=800)
frame1.pack(expand=True, fill='both')
canvas = tk.Canvas(frame1, width=900, height= 900)
canvas.pack(side='left', fill='both', expand=True)
vsb = tk.Scrollbar(frame1, orient='vertical')
vsb.pack(fill='y', side='right', expand=False)
vsb.configure(command=canvas.yview)
item_1 = tk.Frame(canvas, bg='red', width=500, height=500)
canvas.create_window(0, 0, window=item_1, anchor='nw')
item_2 = tk.Frame(canvas, bg='green', width=500, height=500)
canvas.create_window(500, 500, window=item_2, anchor='nw')
canvas.configure(yscrollcommand=vsb.set, scrollregion=canvas.bbox("all"))
#root.after(100, resize)
root.mainloop()