Tkinter Side Bar

Question:

enter image description here

I want to create a side bar like the one ABOVE that is collapsible.
In the collapsed form, the side bar will only have icons for the option and when you hover your mouse over the bar then it will expand showing you the description/name of the icon.
If you click on the icon then it will take you to a function designated to that icon such as settings page.
On the right I will have the main home page with a lot of buttons.
I have no clue how you would do this so please help me start this off and I should manage with the rest.
Is it also possible to do this with only the basic Tkinter or do I need to import more modules via pip (not preferable)
So far I have this:

def loginnow(name):
global login
login.destroy()
login= Tk()
screen_width = login.winfo_screenwidth()
screen_height = login.winfo_screenheight()
screen_height=str(screen_height)
screen_width=str(screen_width)
screen = screen_width+"x"+screen_height
login.geometry(screen)
login.title("Logged in as %s"%name)

The side bar will include
Settings = https://www.iconpacks.net/icons/2/free-settings-icon-3110-thumb.png
I will manage with the other icons, once I get a general idea.
I want the menu to be visible without having to click on something for it to appear.

Asked By: Bond 007

||

Answers:

Although tkinter doesn’t have anything like this built-in, you have all of the tools to implement it. You start by creating a frame to hold the sidebar, and then bind to the <Enter> and <Leave> events on the frame to show and hide it.

There are at least three ways to show and hide it. For example, if each item was a button with an image and text and added to the frame with pack you could simply add or remove the text portion of the button to cause it to shrink or example.

Or, if using grid and creating the icon and text as separate widgets, you could use grid_remove to remove everything in the second column, causing the frame to shrink.

Or, you could use place to add the sidebar to the root window, and use place to change the width of the frame when you show or hide it.

Answered By: Bryan Oakley

Explanation:

This can actually be achieved by playing around with bindings. Take a look at this rough example below:

from tkinter import *
from PIL import Image, ImageTk

root = Tk()
root.geometry('600x600')

min_w = 50 # Minimum width of the frame
max_w = 200 # Maximum width of the frame
cur_width = min_w # Increasing width of the frame
expanded = False # Check if it is completely exanded

def expand():
    global cur_width, expanded
    cur_width += 10 # Increase the width by 10
    rep = root.after(5,expand) # Repeat this func every 5 ms
    frame.config(width=cur_width) # Change the width to new increase width
    if cur_width >= max_w: # If width is greater than maximum width 
        expanded = True # Frame is expended
        root.after_cancel(rep) # Stop repeating the func
        fill()

def contract():
    global cur_width, expanded
    cur_width -= 10 # Reduce the width by 10 
    rep = root.after(5,contract) # Call this func every 5 ms
    frame.config(width=cur_width) # Change the width to new reduced width
    if cur_width <= min_w: # If it is back to normal width
        expanded = False # Frame is not expanded
        root.after_cancel(rep) # Stop repeating the func
        fill()

def fill():
    if expanded: # If the frame is exanded
        # Show a text, and remove the image
        home_b.config(text='Home',image='',font=(0,21))
        set_b.config(text='Settings',image='',font=(0,21))
        ring_b.config(text='Bell Icon',image='',font=(0,21))
    else:
        # Bring the image back
        home_b.config(image=home,font=(0,21))
        set_b.config(image=settings,font=(0,21))
        ring_b.config(image=ring,font=(0,21))

# Define the icons to be shown and resize it
home = ImageTk.PhotoImage(Image.open('home.png').resize((40,40),Image.ANTIALIAS))
settings = ImageTk.PhotoImage(Image.open('settings.png').resize((40,40),Image.ANTIALIAS))
ring = ImageTk.PhotoImage(Image.open('ring.png').resize((40,40),Image.ANTIALIAS))

root.update() # For the width to get updated
frame = Frame(root,bg='orange',width=50,height=root.winfo_height())
frame.grid(row=0,column=0) 

# Make the buttons with the icons to be shown
home_b = Button(frame,image=home,bg='orange',relief='flat')
set_b = Button(frame,image=settings,bg='orange',relief='flat')
ring_b = Button(frame,image=ring,bg='orange',relief='flat')

# Put them on the frame
home_b.grid(row=0,column=0,pady=10)
set_b.grid(row=1,column=0,pady=50)
ring_b.grid(row=2,column=0)

# Bind to the frame, if entered or left
frame.bind('<Enter>',lambda e: expand())
frame.bind('<Leave>',lambda e: contract())

# So that it does not depend on the widgets inside the frame
frame.grid_propagate(False)

root.mainloop()

I have explained the code using comments to understand on-the-go. The icons where taken from Flat Icons. As can be seen, it has its own disadvantage, but you can quite mimic something closer to what you have shown, with this. You can improve this more by creating custom widgets to hold both icon and text when expanded and so on.

Output:

Updated image code(without PIL):

home = PhotoImage(file='home.png') # Make sure the image size is comparable to the minimum frame width
settings = PhotoImage(file='settings.png')
ring = PhotoImage(file='ring.png')
Answered By: Delrius Euphoria

can you please tell me how can I add a content on the other side of the frame?

Answered By: Ae Santos
Categories: questions Tags: , ,
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.