Is there a way using Tkinter to have buttons so that they are always placed a certain number of pixels from the edge of the window, even when the window is resized? I've tried using anchors but that didn't seem to move the placement in the window that much.
You can anchor buttons or any other widget to the sides of a window by starting with a Frame, and configuring its rows and columns to have a weight of 1 in order for it to fill the parent window.
import Tkinter as tk
import ttk
root = tk.Tk()
frame = ttk.Frame(root)
frame.pack(fill=tk.BOTH, expand=True)
frame.columnconfigure(index=0, weight=1)
frame.columnconfigure(index=2, weight=1)
frame.rowconfigure(index=0, weight=1)
frame.rowconfigure(index=2, weight=1)
Then, for each button you want to use sticky to anchor it to the respective side, and use padx or pady to add some padding (in pixels) between the button and the window.
top_padding = 5
top = ttk.Button(frame, text="Top")
top.grid(row=0, column=1, sticky=tk.N, pady=(top_padding, 0))
left_padding = 5
left = ttk.Button(frame, text="Left")
left.grid(row=1, column=0, sticky=tk.W, padx=(left_padding, 0))
right_padding = 5
right = ttk.Button(frame, text="Right")
right.grid(row=1, column=2, sticky=tk.E, padx=(0, right_padding))
bottom_padding = 5
bottom = ttk.Button(frame, text="Bottom")
bottom.grid(row=2, column=1, sticky=tk.S, pady=(0, bottom_padding))
root.mainloop()
have you tried using the padx function?
it works like this:
button=Button(place,text="something something", padx=10)
it provides with extra horizontal padding between widgets, aditionally, you could use frames with padx and an anchor so the text is fixated to a position
Related
So im having trouble making a horizontal scroll bar with grid and have been trying to mix and match different parameters and such and I've hit a rock with this tutorial
https://newbedev.com/tkinter-canvas-scrollbar-with-grid
being the first example
this is my code so far
window = tk.Tk()
window.geometry("1200x600")
frame_main = tk.Frame(window, bg="gray")
frame_main.grid(sticky='news')
# Create a frame for the canvas with non-zero row&column weights
frame_canvas = tk.Frame(frame_main)
frame_canvas.grid(row=0, column=0, pady=(5, 0), sticky='nw')
frame_canvas.grid_rowconfigure(0, weight=1)
frame_canvas.grid_columnconfigure(0, weight=1)
# Add a canvas in that frame
canvas = tk.Canvas(frame_canvas, bg="yellow")
canvas.grid(row=2, column=2, sticky="news")
# Link a scrollbar to the canvas
vsb = tk.Scrollbar(window, orient="horizontal", command=canvas.xview)
vsb.grid(row=0, column=2, sticky='we')
canvas.configure(xscrollcommand=vsb.set)
frame_canvas.config(width=first5columns_width + vsb.winfo_width(),height=first5rows_height)
canvas.config(scrollregion=canvas.bbox("all"))
col_0_head = tk.Label(window, text = " Adventures_Sherlock_Holmes.txt ", pady = 20) # pady = 20 gives some vertical
# separation between this row and the next
col_0_head.grid(row = 0, column = 0)
col_1_head = tk.Label(window, text = " Age_Innocence.txt ")
col_1_head.grid(row = 0, column = 1)
col_2_head = tk.Label(window, text = " Alice_Wonderland.txt ")
col_2_head.grid(row = 0, column = 2)
window.mainloop()
If you want to create a scroll bar in tkitner using grid option, you can simply create a scrollframe and pack the scrollbar in that frame
This is the type of code you can write:
scrollframe = Frame(root)
scrollframe.grid(...)
scrollx = Scrollbar(scrollframe, orient=HORIZONTAL)
scrollx.pack(expand=1, fill=X, side=BOTTOM)
This should ideally work if you don't want the scrollbar to fill your entire GUI Bottom X-axis. In case you are ok with it filling the entire GUI, then just pack the scrollbar in your root or Tk widget.
Thank You!
Two problems in your code.
The first is no scrollregion in canvas.
The second is wrong grid row and column values.
Here's a code snippet that solves your problem.
# Add a canvas in that frame
canvas = tk.Canvas(frame_canvas, bg="yellow", scrollregion = "0 0 2000 2000")
canvas.grid(row=2, column=2, sticky="news")
# Link a scrollbar to the canvas
vsb = tk.Scrollbar(window, orient="horizontal", command=canvas.xview)
vsb.grid(row=1, column=0, sticky='ew')
canvas.configure(xscrollcommand=vsb.set)
I am trying to place a label and a button widgets at row=0 and different columns, inside a nested frame (i.e result frame). But inside result frame, label and button widgets appears in the center. Can you me to place widgets on intended positions.
import tkinter as tk
window = tk.Tk()
window.title("ASA Downloader")
window.geometry("400x400")
frame1 = tk.LabelFrame(window, padx=5, pady=5, height="200")
#Labels
weight_label = tk.Label(frame1, text= "Weight")
height_label = tk.Label(frame1, text= "Height")
weight_label.grid(row=0,column=0)
height_label.grid(row=1,column=0)
result_frame = tk.LabelFrame(frame1, text="result frame")
result_frame.grid(row=2, column=0)
result_lable= tk.Label(result_frame, text=" result is none")
result_lable.grid(row=0, column=0)
button = tk.Button(result_frame, text="My button inside nested frame")
button.grid(row=1, column=0)
frame1.place(relx=.5, rely=.5, anchor="center")
window.mainloop()
By default, widgets are centered by grid unless you tell it to do otherwise. You aren't telling it to do otherwise, so that is what is happening.
The width of the column is being set by the widest thing in the column. In this case the width of column 0 is the width of the inner frame (which itself is controlled by the width of the button). Since the column is widget than the labels, the labels are centered.
If you are wanting the width and height labels to be on the left, the simplest solution is to set the sticky option to "w" (for west).
weight_label.grid(row=0,column=0, sticky="w")
height_label.grid(row=1,column=0, sticky="w")
Another option would be to set sticky to "ew" (east-west) so that the widget expands to fill the column. You can then set the "anchor" attribute of each label to "w" so that the text is left-aligned. The choice of which solution to use depends a bit on whether you plan to have other widgets in your window.
weight_label = tk.Label(frame1, text= "Weight", anchor="w")
height_label = tk.Label(frame1, text= "Height", anchor="w")
weight_label.grid(row=0,column=0, sticky="ew")
height_label.grid(row=1,column=0, sticky="ew")
scrollbar in Top level window created for a canvas is not working and how do I get region of canvas. where canvas size varies with number of buttons in it
I have created frame in tk(root) and one widget in a frame creates Top level window , which has multiple Buttons in a Frame.Number of Button varies with list. That Frame(which has buttons in it) exists in a canvas. My problem is that after putting scroll widget canvas do not moves
from tkinter import *
root = Tk()
root.geometry("500x200")
my_app= Frame(root)
my_app.pack()
my_window = Toplevel(my_app, bg='brown')
my_window.geometry("500x200+300+500")
top_window = Frame(my_window, bd=2, relief=SUNKEN)
top_window.grid_columnconfigure(0, weight=1)
yscrollbar = Scrollbar(top_window)
yscrollbar.grid(row=0, column=1, sticky=N+S)
canvas = Canvas(top_window, bd=0, yscrollcommand=yscrollbar.set)
canvas.config(scrollregion=(0, 0, 500, 1000))
canvas.grid(row=0, column=0, sticky=N+S+E+W)
yscrollbar.config( command = canvas.yview)
top_window.pack()
my_f = Frame(canvas)
def ins_ind(m):
print(m)
results =
["one","two","three","four","five","six","seven","eight","nine","ten"]
ins_list=[]
for ind, result in enumerate(results):
ins=str(result)
ins_list.append(ind)
ins_list[ind] = Button(my_f, text = ins, font='Times 12 bold',
bg='sandy brown',anchor=E, fg="black", command = lambda m=ins:
ins_ind(m) )
ins_list[ind].pack()
my_f.pack()
root.mainloop()
Scroll bar do no moves
For the buttons to move when you scroll the canvas you must put the buttons on the canvas.
Your code puts the buttons on the frame my_f. To put the buttons on the canvas you should use: canvas.create_window(x, y, window=button).
I want to switch the frame, but not able to do it
1st Page(frame) should have red background color and "Hello" button and Frame size should have 900x650 as window size. When press "Hello" button it should swap to 2nd frame
2nd page (frame) should have green background color and "Hello" button and Frame size should have 900x650 as window size. When press "Hello" button it should swap to 1st frame
import Tkinter as tk
def raise_frame(frame):
print "Inside raise frame"
frame.tkraise()
root = tk.Tk()
root.geometry("900x650+220+20")
root.title("Testing")
frame1 = tk.Frame(root, width=900, height=650, background="red")
frame2 = tk.Frame(root, width=900, height=650, background="green")
B1= tk.Button(frame1, text="Hello", width =10, height=2, command = lambda:raise_frame(frame2)).place (x=200, y=200)
B2= tk.Button(frame2, text="Hello", width =10, height=2, command = lambda:raise_frame(frame1)).place (x=400, y=400)
frame1.pack( )
frame2.pack( )
root.mainloop()
Since you are using pack(), the second frame is placed below the first frame. You can check that by dragging the bottom part of the window. You'll see that there are 2 frames created with the red on the top, and the green on the bottom.
You can use grid() to place the frames on top of each other.
So, replace the lines
frame1.pack()
frame2.pack()
with
frame1.grid(row=0, column=0)
frame2.grid(row=0, column=0)
I would like to display
a window
with a single Frame
and a Label in the Frame which would stretch to the whole width of the window
The following code
import Tkinter as tk
root = tk.Tk()
root.geometry("100x100")
# first column of root will stretch
root.columnconfigure(0, weight=1)
# a frame in root
upper_frame = tk.Frame(root)
# first column of upper_frame will stretch
upper_frame.columnconfigure(0, weight=1)
upper_frame.grid(row=0, column=0)
# a label in upper_frame, which should stretch
mylabel = tk.Label(upper_frame)
mylabel.grid(row=0, column=0)
mylabel.configure(text="hello", background="blue")
root.mainloop()
displays
Why isn't the Label stretching to the whole width of the window but is just as wide as the text?
Specifying sticky option when you call grid (e = east, w = west). Otherwise the widget in the cell is center-aligned.
upper_frame.grid(row=0, column=0, sticky='ew')
..
mylabel.grid(row=0, column=0, sticky='ew')