tkinter: add scrollbar to one frame while i use two - python

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

Related

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.

Scroll bar greyed out in tkinter application

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()
# ^^^^^^^^^^^^

How do I adjust this frame with scrollbar inside the black space?

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()

Tkinter Listbox and Scrollbar not displaying

I am having this issue where the scroll bar is not displaying on the listbox. I do not know what the issue is as.
I believe the issue is originating from the Scrollbar variables as the Listbox appears to be displaying and functioning properly.
The output is displaying the listbox with no scrollbar on the right (as set)
Here is the Listbox with the for loop however, it is displaying the wrong dimensions
Here is the code:
#imports
from tkinter import *
from tkinter import messagebox as ms
from tkinter import ttk
import sqlite3
from PIL import Image,ImageTk
import datetime
global time
time = datetime.datetime.now()
class main:
def __init__(self,master):
self.master = master
def search_user_sql(self):
self.search_user_sqlf = Frame(self.master, height=300, width =200)
scrollbar = Scrollbar(self.search_user_sqlf)
scrollbar.pack(side = RIGHT,fill = BOTH)
myList = Listbox(self.search_user_sqlf, yscrollcommand= scrollbar.set)
myList.pack( side = LEFT, fill = BOTH, expand = 2)
scrollbar.config( command = myList.yview )
self.search_user_sql()
root = Tk()
root.title("Gym Membership System")
main(root)
root.mainloop()
You need to pack the frame to display it. To pack() the frame with the correct size settings, try:
search_user_sqlf = Frame(master, height=300, width=200)
search_user_sqlf.pack(expand=True, fill='both')
search_user_sqlf.pack_propagate(0)
Here is how to attach a scrollbar to list set in a frame in Tkinter:
from tkinter import *
master = Tk()
search_user_sqlf = Frame( master, width=400, height=400)
search_user_sqlf.pack(expand=True, fill='both')
search_user_sqlf.pack_propagate(0)
scrollbar = Scrollbar(search_user_sqlf)
scrollbar.pack(side=RIGHT, fill=Y)
myList = Listbox(search_user_sqlf, yscrollcommand=scrollbar.set)
for line in range(100):
myList.insert(END, "This is line number " + str(line))
myList.pack( side = LEFT, fill = BOTH , expand = 2)
scrollbar.config( command = myList.yview )
mainloop()

Why won't my frame pack python3 tkinter

When I run the code below I do not get an error but the bottom frame doesn't appear in the window please can you tell me why and how I can make it appear (using the pack method NOT GRID please). I am using Python 3.5.0
import tkinter
from tkinter import *
root = tkinter.Tk()
root.geometry("1920x1080")
TopFrame = Frame(root, width=1920, height=200, bg= "green")
TopFrame.pack(side=TOP)
MiddleRightFrame = Frame(root, width=1120, height=730, bg="orange")
MiddleRightFrame.pack(side=RIGHT)
MiddleLeftFrame = Frame(root, width=800, height=730, bg="black")
MiddleLeftFrame.pack(side=LEFT)
BottomFrame = Frame(root, width=1920, height=150, bg="blue")
BottomFrame.pack(side=BOTTOM)
Your MiddleLeftFrame is 800 pixels wide. Your MiddleRightFrame is 1120 pixels. 1120 + 800 = 1920. You're forcing the window to be only 1920 pixels wide, so there's no room for the blue frame.
Remove this line and your frame will appear: root.geometry("1920x1080")
If your intent is for it to appear at the bottom of the window, spanning the entire width of the window, then call pack on it before you call pack on the left and right sides.
Also, I strongly recommend grouping your pack statements together. It makes the code easier to manage in my experience (and I have a lot of experience!).
import tkinter
from tkinter import *
root = tkinter.Tk()
root.geometry("1920x1080")
TopFrame = Frame(root, width=1920, height=200, bg= "green")
MiddleRightFrame = Frame(root, width=1120, height=730, bg="orange")
MiddleLeftFrame = Frame(root, width=800, height=730, bg="black")
BottomFrame = Frame(root, width=1920, height=150, bg="blue")
TopFrame.pack(side=TOP)
BottomFrame.pack(side=BOTTOM)
MiddleRightFrame.pack(side=RIGHT)
MiddleLeftFrame.pack(side=LEFT)
root.mainloop()
The reason this works is due to the packer algorithm. When you place something on the left or right, it will allocate all of the remaining vertical space on that side. Thus, after you pack something on the left and right and then later pack something on the bottom, the "bottom" is the bottom of the space between the left and right, not the bottom of the window as a whole.
Here is the canonical description of how pack works:
http://tcl.tk/man/tcl8.5/TkCmd/pack.htm#M26
I think the issue is that you are using pack sides so that in the middle there is a line of nothing. One way to get around this is to create a MiddleFrame where pack sides are used and then just pack the other frames.
import tkinter
from tkinter import *
root = tkinter.Tk()
root.geometry("1920x1080")
TopFrame = Frame(root, width=1920, height=200, bg= "green")
TopFrame.pack()
#the middle frame
MiddleFrame = Frame(root)
#pack the two middle frames into the frame created above
#the parent of the two middle frames change to become MiddleFrame instead of root
MiddleRightFrame = Frame(MiddleFrame, width=1120, height=730, bg="orange")
MiddleRightFrame.pack(side=RIGHT)
MiddleLeftFrame = Frame(MiddleFrame, width=800, height=730, bg="black")
MiddleLeftFrame.pack(side=RIGHT)
#pack the middle frame with both frames inside it
MiddleFrame.pack()
BottomFrame = Frame(root, width=1920, height=150, bg="blue")
BottomFrame.pack()
Add:
tkinter.mainloop()
so that the GUI starts waiting for events as opposed to skipping to close itself.
Additionally, pack uses a filling algorithm which calculates dynamically to fill the empty space. You shouldn't really be doing it like this but a simple call swap would suffice in this specific case. Call:
BottomFrame.pack(side=BOTTOM)
exactly after TopFrame's pack:
TopFrame.pack(side=TOP)
BottomFrame.pack(side=BOTTOM)
MiddleRightFrame.pack(side=RIGHT)
MiddleLeftFrame.pack(side=LEFT)

Categories