Button Layout with Tkinter?
Button Layout with Tkinter?
I want to make my buttons a 2 x 2 grid on the bottom of the window with a canvas above them but the buttons always seem to stack weird when I use .pack(side = whatever).
A major thing I also want the buttons and canvas to have relative size i.e. % so that whenever the window is resized the buttons still make up the right area.
I am not sure how to do this being new to tkinter and any help is appreciated.
import tkinter
from tkinter import *
code = Tk()
def LAttack():
print(something);
def HAttack():
print(something);
def FField():
print(something);
def Heal():
print(something);
def Restart():
print(something);
Attack1 = tkinter.Button(code,text = ("Light Attack"), command = LAttack)
Attack1.pack(side = LEFT)
Attack2 = tkinter.Button(code,text = ("Heavy Attack"), command = HAttack)
Attack2.pack(side = RIGHT)
Defense1 = tkinter.Button(code,text = ("Forcefield"), command = FField)
Defense1.pack(side = LEFT)
Defense2 = tkinter.Button(code,text = ("Heal"), command = Heal)
Defense2.pack(side = RIGHT)
Restart1 = tkinter.Button(code,text = ("Restart"), command = Restart)
Restart1.pack(side = TOP)
code.mainloop()
But I want it to look like this:
Mock up for GUI
If you are creating a grid of buttons, have you read up on how to use the
grid
geometry manager?– Bryan Oakley
Sep 13 '18 at 14:29
grid
1 Answer
1
I want to make my buttons a 2 x 2 grid on the bottom of the window with a canvas above them but the buttons always seem to stack weird when I use .pack(side = whatever).
To me this means that you clearly have two separate areas to be concerned with: a top area with a canvas, and a bottom area with buttons. The first step is to create those two areas. For the top just use the canvas, and for the bottom use a frame.
I'm going to assume you want the canvas to take up as much space as possible, with the buttons always on the bottom. For that sort of arrangement, pack
makes the most sense.
pack
The following gives us a program that has a canvas at the top and a frame at the bottom to hold the buttons. When you resize the window, the button frame remains at the bottom and the canvas fills the rest of the space:
import tkinter as tk
root = tk.Tk()
canvas = tk.Canvas(root, background="white")
button_frame = tk.Frame(root)
button_frame.pack(side="bottom", fill="x", expand=False)
canvas.pack(side="top", fill="both", expand=True)
# <button code will be added here...>
root.mainloop()
Now we can focus on the buttons. You want the buttons in a 2x2 grid (though you have 5 buttons...?), so the natural choice is to use grid
rather than pack
. We want these buttons to be in the bottom frame, so we give that frame as the parent or master of the buttons.
grid
pack
You also somewhat curiously wrote "whenever the window is resized the buttons still make up the right area" even though earlier you said you wanted them on the bottom. I'm going to assume you mean that you want them in the bottom-right corner.
To accomplish this, we are going to create a grid with two rows and three columns. The column on the left will be empty, and it will take up any extra space to force the buttons to be on the right (of course, you can put things in this column if you wish)
This creates four buttons:
attack1 = tk.Button(button_frame, text="Light Attack")
attack2 = tk.Button(button_frame, text="Heavy Attack")
defense1 = tk.Button(button_frame, text="Forcefield")
defense2 = tk.Button(button_frame, text="Heal")
... this causes the first column to expand to fill any extra space:
button_frame.grid_columnconfigure(0, weight=1)
... and this lays them out in a grid (it's always good to separate widget creation from widget layout, because it makes it easier to visualize the layout in the code)
attack1.grid(row=0, column=1, sticky="ew")
attack2.grid(row=0, column=2, sticky="ew")
defense1.grid(row=1, column=1, sticky="ew")
defense2.grid(row=1, column=2, sticky="ew")
The end result is this:
When resized, the buttons retain their relative position:
The point of this is to show that you need to spend a few minutes organizing the items on the screen into logical groups. There are different layout tools for solving different problems (grid
, pack
, place
), and most windows will benefit from using the right tool for each type of layout problem you're trying to solve (pack
is good for horizontal and vertical layouts, grid
is good for grids, and place
covers a few edge cases where pixel-perfect control is needed).
grid
pack
place
pack
grid
place
This looks great but a few questions. Could I make the frame change size relative to window so when it gets bigger the frame gets bigger. And 2 can you make the buttons fill up 50% of the frame width wise. Thanks.
– Roberto Chavo
Sep 13 '18 at 21:58
@RobertoChavo: that's exactly what the code does, and the screenshots show it. The frame automatically got widget when I resized the windows. And yes, you can make the buttons fill up 50% of the screen. There are plenty of options to do what you want.
– Bryan Oakley
Sep 13 '18 at 22:33
so I could make it look like my mock up that I posted?
– Roberto Chavo
Sep 14 '18 at 13:45
@RobertoChavo: yes, of course. Tkinter's geometry managers are very powerful. There's probably no design you could come up with that you can't do with some combination of
pack
, place
, and/or grid
.– Bryan Oakley
Sep 14 '18 at 14:07
pack
place
grid
I really can't figure out how. I change the column span to make the buttons bigger but they don't change size. I change the columns and rows and the buttons don't move.
– Roberto Chavo
Sep 16 '18 at 22:23
Thanks for contributing an answer to Stack Overflow!
But avoid …
To learn more, see our tips on writing great answers.
Required, but never shown
Required, but never shown
By clicking "Post Your Answer", you acknowledge that you have read our updated terms of service, privacy policy and cookie policy, and that your continued use of the website is subject to these policies.
Hi there. Please would you post your code in the question so that others can identify what your problem is. Thanks! Also might help to include an image of your resulting layout.
– feedMe
Sep 13 '18 at 13:32