Scroll bar greyed out in tkinter application - python

I am trying to add a scroll bar into my tkinter application. It is appearing, however it is greyed out and is not able to scroll and I am not sure why despite the fact that I have many widgets beyond the height of the page. Any help would be appreciated.
import calendar
import tkinter as tk
from tkinter import ttk
root = tk.Tk()
root.geometry('800x800')
x = 30
y = 30
box_image = tk.PhotoImage(file='apple.png')
### SCROLL BAR ###
# create a main frame
main_frame = tk.Frame(root)
main_frame.pack(fill='both', expand=1)
# create a canvas
my_canvas = tk.Canvas(main_frame)
my_canvas.pack(side='left', fill='both', expand=1)
# add a scrollbar to the canvas
my_scrollbar = ttk.Scrollbar(main_frame, orient='vertical', command=my_canvas.yview)
my_scrollbar.pack(side='right', fill='y')
# configure the canvas
my_canvas.configure(yscrollcommand=my_scrollbar.set)
my_canvas.bind('<Configure>', lambda e: my_canvas.configure(scrollregion = my_canvas.bbox("all")))
# create Another frame inside the canvas
second_frame = tk.Frame(my_canvas)
# add that new frame to a window in the canvas
my_canvas.create_window((0,0), window=second_frame, anchor="nw")
def display():
global x , y
panel2 = tk.Label(main_frame, image=box_image, bg='#f7f6f6')
panel2.place(x=x, y=y)
x = x
y = y+200
button = tk.Button(main_frame, text="click me", command=display)
button.place(x=0, y=0)
for thing in range (100):
tk.Button(main_frame, text=f'Button {thing}Yo!').pack()
root.mainloop()

For the frame-in-a-canvas trick to work, you must add the buttons to the inner frame:
for thing in range (100):
tk.Button(second_frame, text=f'Button {thing}Yo!').pack()
# ^^^^^^^^^^^^

Related

Making a window UI scroll down and deleting labels from frame

I am making a random generator for my friends and I'm stuck trying to make a scroll down option. So if you generate more the window can show, a scroll down window should be possible. But I can't seem to get any to work. I've tried many online tutorials.
And my second issue with my code is that I can't clear the generated labels from the window. I got it working that it expands the window.
from cProfile import label
from pickle import FRAME
import random
import tkinter as tk
from tkinter import BOTH, DISABLED, LEFT, RIGHT, VERTICAL, Y, Frame, Label, filedialog, Text
import os
from tkinter import ttk
from tkinter.font import NORMAL
from tkinter.messagebox import YES
root = tk.Tk()
root.title('guesser')
#Pelin arvonta ohjelma !
def delete():
for child in root.children.values():
info = child.grid_info()
if info['column'] == 0:
child.grid_forget()
def arvonta():
global label
list1 = []
lista = ["Valorant","Rainbow","Vampire: The masquerade","Playerunknown's battlegrounds","Fortnite","Left 4 Dead 2","Counter strike Global offensive","Realm roayale","Black ops 1 zombies/multiplayer","Black ops 2 zombies/multiplayer","Black ops 3 zombies/multiplayer"]
numero = random.randint(0, 10)
hahmo = (lista[numero])
list1.append(hahmo)
for app in list1:
label = tk.Label(frame, text=app, bg="red",font=('Helvetica',20))
label.pack()
def valorant():
list2 = []
lista2 = ["Brimstone","Viper","Omen","Killjoy","Cypher","Sova","Sage","phoenix","Jett","Reyna","Raze","Raze","Breach","Skye","Yoru","Astra","Kay/o","Chamber","Neon","Fade"]
numero = random.randint(0, 19)
randomValorantagent=(lista2[numero])
list2.append(randomValorantagent)
for app in list2:
label = tk.Label(frame, text=app, bg="red",font=('Helvetica',20))
label.pack()
def quitter():
quit()
canvas = tk.Canvas(root,height=700,width=700,bg="#263D42")
canvas.pack(side=LEFT,fill=BOTH,expand=1)
frame = tk.Frame(root,bg="green")
frame.place(relwidth=0.8,relheight=0.8,relx=0.1,rely=0.1)
frame.pack(fill=BOTH,expand=1)
my_scrollbar = ttk.Scrollbar(frame, orient=VERTICAL, command=canvas.yview)
my_scrollbar.pack(side=RIGHT, fill=Y)
# Configure The Canvas
canvas.configure(yscrollcommand=my_scrollbar.set)
canvas.bind('<Configure>', lambda e: canvas.configure(scrollregion = canvas.bbox("all")))
# Create ANOTHER Frame INSIDE the Canvas
second_frame = Frame(canvas)
# Add that New frame To a Window In The Canvas
canvas.create_window((0,0), window=second_frame, anchor="nw")
#rlls the game
openfile = tk.Button(second_frame,text="Roll a game",padx=10,pady=5,fg="white",bg="#263D42", command=arvonta)
openfile.pack()
#rolls a valorant agent
valorantA = tk.Button(second_frame,text='Roll valorant agent',padx=10,pady=5,fg="white",bg="#263D42",command=valorant)
valorantA.pack()
# stops program
stop = tk.Button(second_frame,text="Quit",padx=10,pady=5,fg="white",bg="#263D42",command=quitter)
stop.pack()
# deletes all info from screen.
deletor = tk.Button(second_frame,text="delete info",padx=10,pady=5,fg="white",bg="#263D42",command=delete)
deletor.pack()
root.mainloop()```
The following does most of what you want. I wrote it some time ago to test Scrollbars because they are wonky IMHO
from tkinter import *
from functools import partial
class ButtonsTest:
def __init__(self):
self.top = Tk()
self.top.title("Click a button to remove")
self.top.geometry("425x200+50+50")
Label(self.top, text=" Click a button to remove it ",
bg="lightyellow", font=('DejaVuSansMono', 12)
).grid(row=0, sticky="nsew")
Button(self.top, text='Exit', bg="orange", width=9,
command=self.top.quit).grid(row=1,column=0,
sticky="nsew")
self.add_scrollbar()
self.button_dic = {}
self.buttons()
self.top.mainloop()
##-------------------------------------------------------------------
def add_scrollbar(self):
self.canv = Canvas(self.top, relief=SUNKEN)
self.canv.config(width=400, height=200)
self.top_frame = Frame(self.canv, height=100)
##---------- scrollregion has to be larger than canvas size
## otherwise it just stays in the visible canvas
self.canv.config(scrollregion=(0,0, 400, 500))
self.canv.config(highlightthickness=0)
ybar = Scrollbar(self.top, width=15, troughcolor="lightblue")
ybar.config(command=self.canv.yview)
## connect the two widgets together
self.canv.config(yscrollcommand=ybar.set)
ybar.grid(row=3, column=2, sticky="ns")
self.canv.grid(row=3, column=0)
self.canv.create_window(1,0, anchor=NW,
window=self.top_frame)
##-------------------------------------------------------------------
def buttons(self):
b_row=1
b_col=0
for but_num in range(1, 51):
## create a button and send the button's number to
## self.cb_handler when the button is pressed
b = Button(self.top_frame, text = str(but_num), width=5,
command=partial(self.cb_handler, but_num))
b.grid(row=b_row, column=b_col)
## dictionary key=button number --> button instance
self.button_dic[but_num] = b
b_col += 1
if b_col > 4:
b_col = 0
b_row += 1
##----------------------------------------------------------------
def cb_handler( self, cb_number ):
print("\ncb_handler", cb_number)
self.button_dic[cb_number].grid_forget()
##===================================================================
BT=ButtonsTest()

Tkinter widgets in a notebook tab only showing when mouse is moved off of the tab label

I recently made 2 functions, add_scrollbar and update_scroll_region, which adds a scrollbar to a given frame and updates the scroll region when widgets in that frame change.
The frame in which I am adding a scrollbar is a notebook tab. The functions work as intended, but when I switch off a tab with the scrollbar (and only the ones with the scrollbar) and come back to it, all the widgets are gone. If I move my mouse off of the tab label, all the widgets re-appear. I am not exactly sure what it is about these 2 functions that could be causing this kind of behavior. I have provided a simplified example below. In this example, TAB1 has the scrollbar, and TAB2 does not. You will notice that switching from TAB2 to TAB1 hides the button in TAB1 until the mouse is moved.
from tkinter import *
from tkinter import ttk
root = Tk()
root.geometry("1200x1200")
def add_scrollbar(outer_frame):
canvas = Canvas(outer_frame)
canvas.pack(side=LEFT, fill=BOTH, expand=1)
information_frame = Frame(canvas)
canvas.create_window((0, 0), window=information_frame)
scrollbar = ttk.Scrollbar(outer_frame, orient=VERTICAL, command=canvas.yview)
scrollbar.pack(side=RIGHT, fill=Y)
canvas.configure(yscrollcommand=scrollbar.set)
return information_frame, canvas
def update_scroll_region(canvas):
global root
root.update()
bbox = canvas.bbox("all")
x, y, width, height = bbox
if height < canvas.winfo_height():
bbox = x, y, width, canvas.winfo_height()
canvas.configure(scrollregion=bbox)
return
def create_example():
global root
notebook = ttk.Notebook(root, height=1200, width=1500)
notebook.pack(pady=10)
my_outer_frame_1 = Frame(root)
my_outer_frame_1.pack(fill=BOTH, expand=1)
notebook.add(my_outer_frame_1, text="TAB1")
inner_frame_1, my_canvas_1 = add_scrollbar(my_outer_frame_1)
my_outer_frame_2 = Frame(root)
my_outer_frame_2.pack(fill=BOTH, expand=1)
notebook.add(my_outer_frame_2, text="TAB2")
Label(my_outer_frame_2, text="This always shows").pack()
# ^^^ Sets up a notebook with 2 tabs
changing_frame = Frame(inner_frame_1, borderwidth=4) # this is the frame that will be changing its contents
changing_frame.pack(side=LEFT, anchor="n")
display_frame(changing_frame, my_outer_frame_1, my_canvas_1)
# this method re-displays the changing frame depending on the specified size ('big' or 'small')
root.mainloop()
return
def display_frame(frame, outer_frame, canvas, size='small'):
for widget in frame.winfo_children():
widget.destroy()
if size == 'small':
Button(frame, text="This button is gone until the mouse is moved",
command=lambda this_frame=frame: display_frame(this_frame, outer_frame, canvas, size='big')).grid(row=0,
column=0)
elif size == 'big':
Button(frame, height=5, width=5, text="Hide",
command=lambda this_frame=frame: display_frame(this_frame, outer_frame, canvas, size='small')).grid(
row=0, column=0)
for n in range(1, 100):
Label(frame, text="Other Stuff!").grid(row=n, column=0)
update_scroll_region(canvas)
return
if __name__ == '__main__':
create_example()

How to get tkinter scroll bar working (greyed out)

I am creating a simple tkinter application. When the user presses a button an image appears. If they press it again another image appears etc. So I am wanting a scroll bar so that the user can scroll to the images that appear off the page. I am not sure what I have done wrong but the scroll bar is greyed out and is not working.
import calendar
import tkinter as tk
from tkinter import ttk
root = tk.Tk()
root.geometry('800x800')
x = 30
y = 30
box_image = tk.PhotoImage(file='apple.png')
### SCROLL BAR ###
# create a main frame
main_frame = tk.Frame(root)
main_frame.pack(fill='both', expand=1)
# create a canvas
my_canvas = tk.Canvas(main_frame)
my_canvas.pack(side='left', fill='both', expand=1)
# add a scrollbar to the canvas
my_scrollbar = ttk.Scrollbar(main_frame, orient='vertical', command=my_canvas.yview)
my_scrollbar.pack(side='right', fill='y')
# configure the canvas
my_canvas.configure(yscrollcommand=my_scrollbar.set)
my_canvas.bind('<Configure>', lambda e: my_canvas.configure(scrollregion = my_canvas.bbox("all")))
# create Another frame inside the canvas
second_frame = tk.Frame(my_canvas)
# add that new frame to a window in the canvas
my_canvas.create_window((0,0), window=second_frame, anchor="nw", width="10000")
def display():
global x , y
panel2 = tk.Label(main_frame, image=box_image, bg='#f7f6f6')
panel2.place(x=x, y=y)
x = x
y = y+200
button = tk.Button(second_frame, text="click me", command=display)
button.place(x=0, y=0)
label = tk.Label(second_frame, text="label", bg="blue")
label.pack(fill="x", padx=50)
new_frame = tk.Frame(second_frame, bg='black', height=110)
new_frame.pack(fill="x")
root.mainloop()
You need to put the image in second_frame, not in main_frame.

tkinter: add scrollbar to one frame while i use two

in this code i try to add two frames one on the left and second on the right and i need to make the left frame fixed and add scrollbar on the right frame
from tkinter import *
from tkinter import ttk
from tkinter.ttk import *
win_width = 1200
win_hight = 720
root=Tk()
root.geometry("{}x{}".format(str(win_width),str(win_hight)))
frame_style = Style()
frame_style.configure('blue.TFrame', background='#1d96f4',highlightthickness=0)
frame_style.configure('white.TFrame', background='#FFFFFF',highlightthickness=0)
frame1 = ttk.Frame(root, style='blue.TFrame')
frame1.grid(row=0,column=0)
frame1.config(width=win_width*(50/100.0),height=win_hight, relief=RIDGE)
frame1.grid_propagate(0)
frame2 = ttk.Frame(root, style='white.TFrame')
frame2.grid(row=0,column=2)
frame2.config(width=win_width*(50/100.0),height=win_hight, relief=RIDGE)
frame2.grid_propagate(0)
my_canvas = Canvas(frame2, background="white",width=1100,height=720)
my_canvas.pack(side=LEFT,fill=Y)
my_scrollbar = ttk.Scrollbar(frame2, orient=VERTICAL , command=my_canvas.yview)
my_scrollbar.pack(side=RIGHT, fill=Y)
my_canvas.configure(yscrollcommand=my_scrollbar.set)
my_canvas.bind('<Configure>', lambda e: my_canvas.configure(scrollregion = my_canvas.bbox("all")))
second_frame = Frame(my_canvas)
my_canvas.create_window((1200,720), window=second_frame)
for i in range(0,50):
title_label = Label(second_frame, text="Test",background='#1d96f4',foreground="#FFFFFF",font=('Helvetica', 22, 'bold'))
title_label.place(x=20, y=40*i)
root.mainloop()
I have tried various methods but have not been able to set the look properly and I don't want to use "pack" at least inside the right frame

Python tkinter how to zoom in widgets

My code:
import tkinter as tk
root = tk.Tk()
for i in range(50):
for j in range(50):
tk.Button(height=1, width=2, bg='Blue').grid(row=j, column=i)
root.mainloop()
I can not see all of the buttons in the screen even when I maxmize the window. so I want to add an option to zoom out (all of the widgets will be smaller) so I can see all of them. How do I do that?
Example code:
import tkinter as tk
root = tk.Tk()
root.state('zoomed')
widgets_to_zoom_list = []
DEFAULT_SIZE = 50
def zoom(widget):
for every_widget in widgets_to_zoom_list:
every_widget.config(width=widget.get(), height=widget.get())
def main():
canvas = tk.Canvas(root)
frame = tk.Frame(canvas)
zoom_scale = tk.Scale(root, orient='vertical', from_=1, to=100)
zoom_scale.config(command=lambda args: zoom(zoom_scale))
zoom_scale.set(DEFAULT_SIZE)
pixel = tk.PhotoImage(width=1, height=1)
for i in range(50):
btn = tk.Button(frame, text=str(i + 1), bg='Blue', image=pixel, width=DEFAULT_SIZE, height=DEFAULT_SIZE, compound="c")
btn.grid(row=0, column=i)
widgets_to_zoom_list.append(btn)
canvas.create_window(0, 0, anchor='nw', window=frame)
# make sure everything is displayed before configuring the scroll region
canvas.update_idletasks()
canvas.configure(scrollregion=canvas.bbox('all'))
canvas.pack(fill='both', side='left', expand=True)
zoom_scale.pack(fill='y', side='right')
root.mainloop()
if __name__ == '__main__':
main()
From what i have been able to understand from your question, i think you want the window to be resizable in tkinter.
To allow a window to be resized by the user, we use the resizable function -:
root.resizable(height = True, width = True)
In this case the two args are height and width which help you customize if you only want the widget to be vertically resizable or only want it to be horizontally resizable.
Your code with this function added should look like this -:
import tkinter as tk
root = tk.Tk()
root.resizable(True, True) #Assuming you want both vertically and horizontally resizable window.
for i in range(50):
for j in range(50):
tk.Button(height=1, width=2, bg='Blue').grid(row=j, column=i)
root.mainloop()
I hope this will solve your problem.
And I also hope you are safe in this time of an ongoing pandemic.

Categories