Reputation: 220
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.
Upvotes: 4
Views: 16439
Reputation: 15088
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.
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')
Upvotes: 10
Reputation: 385900
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.
Upvotes: 2