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

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

Related

Pack 4 frames inside the window (tkinter)

Good day everyone!
I need to place four frames inside the window as shown in the picture, and using the .pack() method.
Now I have 3 frames placed in the window (picture before), and I want to add another one by moving frame f11 to the right. I also attach a picture with how it should look as a result (picture after).
Current part of code:
f11 = LabelFrame(current_tab, borderwidth=2, pady=5, relief=GROOVE, labelwidget=lbl_frm_wdgt_founder)
f11.pack(side=BOTTOM, fill=BOTH)
frame_left = Frame(current_tab, borderwidth=0, relief=GROOVE)
frame_left.pack(side=LEFT, fill=BOTH)
frame_right = LabelFrame(current_tab, labelwidget=lbl_frm_wdgt_arb, borderwidth=2, relief=GROOVE)
frame_right.pack(side=RIGHT, fill=BOTH)
frame_bottom_left = Frame(current_tab, borderwidth=2, relief=GROOVE)
# frame_bottom_left.pack(???)
If you don't want to / can't use grid(), you can use tk.Frame() widgets as generic containers
import tkinter as tk # don't use star imports!
from tkinter import ttk
top_container = tk.Frame(current_tab)
top_container.pack(expand=True, fill=tk.X, side=tk.TOP)
# top container children
frame_left = Frame(
top_container,
borderwidth=0,
relief=tk.GROOVE
)
frame_left.pack(side=tk.LEFT, fill=tk.BOTH)
frame_right = LabelFrame(
top_container,
labelwidget=lbl_frm_wdgt_arb,
borderwidth=2,
relief=tk.GROOVE
)
frame_right.pack(side=tk.RIGHT, fill=tk.BOTH)
bottom_container = tk.Frame(current_tab)
bottom_container.pack(expand=True, fill=tk.X, side=tk.BOTTOM)
# bottom container children
frame_bottom_left = tk.Frame(
bottom_container,
borderwidth=2,
relief=tk.GROOVE
)
frame_bottom_left.pack(side=tk.LEFT, fill=tk.BOTH)
f11 = ttk.LabelFrame(
bottom_container,
borderwidth=2,
pady=5,
relief=tk.GROOVE,
labelwidget=lbl_frm_wdgt_founder
)
f11.pack(side=tk.RIGHT, fill=tk.BOTH)
Since the container frames are packed separately, you can use one on top and another on the bottom
P.S.: Try to avoid * star imports - make sure to properly namespace all constants e.g. tk.LEFT and classes e.g. ttk.LabelFrame

Choose which part of the panel to resize

I'm trying to figure out how to choose which part of the panel changes sizes when changing the size of the window. The way it goes right now is that every time I change the size of the window, it's the panel on the right or the one on the bottom the ones that change while the one on the left and the one on the top remain the same size. I want it to be the other way around. I want it to be so that the one that changes size is the one on the left, not the one on the right. I've tried changing the different parameters for pack but it affects the whole panel, not just one side.
This is the code I'm using as a reference.
from tkinter import *
root = Tk()
root.title("Hello World!")
root.geometry("400x400")
panel_1 = PanedWindow(bd=4, relief="raised", bg="red")
panel_1.pack(fill=BOTH, expand=1)
left_label = Label(panel_1, text="Left Panel")
panel_1.add(left_label)
panel_2 = PanedWindow(panel_1, orient=VERTICAL, bd=4, relief="raised", bg="blue")
panel_1.add(panel_2)
top = Label(panel_2, text="Top Panel")
panel_2.add(top)
bottom = Label(panel_2, text="Bottm Panel")
panel_2.add(bottom)
root.mainloop()
Here is the modified code following #jasonharper advice.
from tkinter import *
root = Tk()
root.title("Hello World!")
root.geometry("400x400")
panel_1 = PanedWindow(bd=4, relief="raised", bg="red")
panel_1.pack(fill=BOTH, expand=1)
left_label = Label(panel_1, text="Left Panel")
panel_1.add(left_label, stretch="always")
panel_2 = PanedWindow(panel_1, orient=VERTICAL, bd=4, relief="raised", bg="blue")
panel_1.add(panel_2, stretch="never")
top = Label(panel_2, text="Top Panel")
panel_2.add(top)
bottom = Label(panel_2, text="Bottm Panel")
panel_2.add(bottom)
root.mainloop()

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.

Tkinter Canvas Scrollbars stopped working

Intitially when the frame and canvas size were smaller both scrollbars worked fine. After I increased their size to match that of the Toplevel, the x scrollbar disappear and the y one stopped working.
You may say I don't need the x scrollbar, because I adjusted the canvas create_text width attribute to fit the text within the window, and you'd be right, but I am trying to learn how to use scrollbars when the window's maximize button is on and when it's off.
The files I load to read are pretty lengthy, so I need the y scrollbar to scroll all the way to the end of the text. Checking some online notes on the scrollregion, I came a cross one that suggested using n,e,w,s coordintates, but when I use them, I get errores. I used scrollregion=(0,0,500,500) but that seems too finite to me.
from tkinter import *
from tkinter import font
newline=''
fileContent=[]
filePath='file.txt'
lines=open(filePath)
newline=lines.read()
w=Tk()
def openViewer():
pop = Toplevel(w)
pop.title('Operation Report')
pop.geometry("750x500+15+20")
pop.state('zoomed') # Window's Miximize button
frame=Frame(pop,width=780,height=560)
frame.grid(row=0,column=0)
canvas=Canvas(frame, width=780, height=560, background='black')
canvas.config(scrollregion=(0,0,500,500))
canvas.pack(side=LEFT, fill=BOTH)
verdana_font = font.Font(family = "Verdana",size = 13)
canvas.create_text((30, 0), anchor='nw', text=newline,
font=verdana_font, fill = 'light grey',
justify=LEFT, width=750)
hbar=Scrollbar(frame,orient=HORIZONTAL)
hbar.pack(side=BOTTOM,fill=X)
hbar.config(command=canvas.xview)
vbar=Scrollbar(frame,orient=VERTICAL)
vbar.pack(side=RIGHT,fill=Y)
vbar.config(command=canvas.yview)
canvas.config(xscrollcommand=hbar.set, yscrollcommand=vbar.set)
btn=Button(w, text='View Content', command=openViewer)
btn.pack()
w.mainloop()
from tkinter import *
from tkinter import font
newline=''
fileContent=[]
filePath='C:/path to/ file.txt'
lines=open(filePath)
newline=lines.read()
w=Tk()
def openViewer():
pop = Toplevel(w)
pop.title('Operation Report')
pop.geometry("750x500+15+20")
pop.state('zoomed') # Window's Miximize button
frame=Frame(pop,width=780,height=560)
frame.grid(row=0,column=0)
# I decreased the canvas height to show the x scrollbar and removed
# the create_text method width attribute to unwrap the text and
# activate the horizontal scrollbar
canvas=Canvas(frame, width=780,height=530, background='black')
verdana_font = font.Font(family = "Verdana",size = 13)
canvas.create_text((0, 0), anchor='nw', text=newline,
font=verdana_font, fill = 'light grey',
justify=LEFT) # Add this width=750 to wrap text
hbar=Scrollbar(frame,orient=HORIZONTAL)
hbar.pack(side=BOTTOM,fill=X)
hbar.config(command=canvas.xview)
vbar=Scrollbar(frame,orient=VERTICAL)
vbar.pack(side=RIGHT,fill=Y)
vbar.config(command=canvas.yview)
canvas.config(scrollregion=canvas.bbox(ALL))
canvas.config(xscrollcommand=hbar.set, yscrollcommand=vbar.set)
canvas.pack(side=LEFT, expand=True, fill=BOTH)
btn=Button(w, text='View Content', command=openViewer)
btn.pack()
w.mainloop()
Hopefully, this may help someone else with the same or similar problem. :)

Make button on opposite side of tkinter GUI

When I put in my code for this name picker, the gui opens and the two buttons are on top of each other. I understand why this is happening but I do not know how to move it.
This is what it looks like
This is what I want it to look like
Code:
from tkinter import *
import tkinter
import random
names =['Sledge','Thatcher','Ash','Thermite','Twitch','Montagne','Glaz','Fuze','Blitz','IQ','Buck','Blackbeard','Capitão','Hibana']
name = ["Smoke","Mute","Castle","Pulse","Doc","Rook","Kapkan","Tachanka","Jäger","Bandit","Frost","Valkyrie","Caveira","Echo"]
def pickName():
nameLabel.configure(text=random.choice(names))
def pickName1():
nameLabel.configure(text=random.choice(name))
root = tkinter.Tk()
root.title("Operator Picker")
root.geometry("400x100")
nameLabel = tkinter.Label(root, text="", font=('Helvetica', 32))
nameLabel.pack()
Grid()
pickButton1 = tkinter.Button(text="Pick Attack", command=pickName)
pickButton1.pack()
pickButton1.place(bordermode=OUTSIDE,height=100, width= 100)
pickButton2 = tkinter.Button(text="Pick Defend", command=pickName1)
pickButton2.pack()
pickButton2.place(bordermode=OUTSIDE,height=100, width= 100)
root.mainloop()
You don't need to pack and place your buttons, you can just pack them. If you want them on opposite sides, try this
pickButton1 = tkinter.Button(root, text="Pick Attack", command=pickName, height=100, width=100)
pickButton1.pack(side=tkinter.LEFT)
pickButton2 = tkinter.Button(root, text="Pick Defend", command=pickName1, height=100, width=100)
pickButton2.pack(side=tkinter.RIGHT)
Edit:
When you define the width and height of an object containing text, it is measured in lines and characters instead of pixels, if you want those exact sizes, you need to add frames
f1 = tkinter.Frame(root, height=100, width=100) #defines frame size in pixels
f1.pack(side=tkinter.LEFT) #packs on the left
f1.pack_propagate(0) #tells frame not to let children control size
pickButton1 = tkinter.Button(f1, command=pickName, text="Pick Attack")
pickButton1.pack(fill=tkinter.BOTH, expand=1) #takes up all available space
f2 = tkinter.Frame(root, height=100, width=100)
f2.pack(side=tkinter.RIGHT)
f2.pack_propagate(0)
pickButton2 = tkinter.Button(f2, command=pickName1, text="Pick Defend")
pickButton2.pack(fill=tkinter.BOTH, expand=1)

Categories