Find position of another anchor than the anchor already used
I have created a code to show my problem. It looks like this:
userNameID = tkinter.Label(root, text="Name/ID")
userNameID.place(x=640, y=320, anchor="e")
userNameID = tkinter.Label(root, text="Password")
userNameID.place(x=640, y=360, anchor="e")
entButton = tkinter.Button(root, text="Enter", command=enterPrint)
entButton.place(x=640, y=400, anchor="w")
The thing is that I have aligned some text on one size of the center and a button on the other side. I want to know the position of the northwest anchor for the texts to make sure everything is the same distance away from the center and still aligned.
grid()
and pack()
are "precises" enough for most needs. You just need to learn how to properly use these geometry managers to their fullest. In fact the use of place()
is almost never what you need. It has its case uses but it is not a great choice for general GUI setups. It is also very hard to manage for updating your code.
Update: To answer you question in the comments:
Row configure means that you put every row to be 1 pixel because of the weight? I know I can draw a grid over the whole thing but I don't know how many rows, columns my program has. therefore I can't find the center.
The weights are used to tell a specific row or column should resize at a certain ratio in relation to the other rows and columns around them within the same grid/container. The default weight is zero. When we set the weight to 1 then that row or column will resize with the window at an even rate.
Take this example code:
import tkinter as tk
root=tk.Tk()
center_frame = tk.Frame(root)
center_frame.grid(row=1, column=1, sticky='nsew')
tk.Label(center_frame, text='Name/ID').grid(row=0, column=0)
tk.Label(center_frame, text='Password').grid(row=1, column=0)
tk.Button(center_frame, text='Enter').grid(row=2, column=1)
root.mainloop()
Results:
In the above example you will see that the widgets do not move when you resize the window. This is because we have not instructed tkinter to allow any rows or columns to move.
If we add this weight to the program root.rowconfigure(0, weight=1)
:
Then we get this affect:
Next add this root.rowconfigure(2, weight=1)
:
Next add this root.columnconfigure(0, weight=1)
:
Next add this root.columnconfigure(2, weight=1)
:
As you can see with the above images depending on what rows and columns you have set a weight to then the rows and columns will resize accordingly. What we achieve with the above code is to have rows 0 and 2 resize and columns 0 and 2 resize. row 1 column 1
will not resize. So that means anything we place in the row 1 column 1
position will not resize but rather maintain its relative location to the borders. Because we set a frame widget in the row 1 column 1
position and then all of our widgets inside the frame we have effectively made row 1 column 1
the center.
There are as many rows and columns as you tell it to have. Tkinter will automatically adjust the total rows and columns based on what you say. Adding to that it will also make rows and columns with nothing in them a zero size. That means only rows and columns with content(widgets) will actually affect the size of the grid.
Say we have 3 rows and 3 columns. Depending on how we fill it it will change the size of whats being displayed.
In this example anywhere you see an X
shows we put something in the following rows and columns.
In this example we have something in (0,0), (1,1) and (2,2).
ROW
0 1 2
*-------*-------*-------*
| | | |
0 | X | | |
C | | | |
O *-------*-------*-------*
L | | | |
U 1 | | X | |
M | | | |
N *-------*-------*-------*
| | | |
2 | | | X |
| | | |
*-------*-------*-------*
In this example we have something in (0,0) and (2,2).
0 2
*-------*-------*
| | |
0 | X | |
| | |
*-------*-------*
| | |
2 | | X |
| | |
*-------*-------*
In this example we have something in (1,0), (2,1) and (2,2).
0 1 2
*-------*-------*-------*
| | | |
1 | X | | |
| | | |
*-------*-------*-------*
| | | |
2 | | X | X |
| | | |
*-------*-------*-------*
The above examples illustrate what is automatically shown depending on what row and grid you fill with widgets.
As for the arguments like sticky
these are used to manages behavior of each widget. For example if we tell a widget to fill all the space in a given row/column then we would use sticky='nsew'
. If we want a widget to stretch in a given row/column horizontally but not vertically we would use sticky='ew'
for east/west. Keep in mind the sticky argument is for grid()
. The pack()
geometry manager has it own arguments.
There are many options and you can find a list of them here with their descriptions:
For grid()
For pack()
Take the below example. This code will set up the labels and button cent of the window at all times even when you resize the window. This is far easier to manage than place.
There are many useful arguments you can use in your geometry managers to achieve just about any behavior or alignment you wish. Just take the time to dig into it. I know place()
feels like the best option (I thought the same when I first started before Bryan corrected that notion :D) but it really is not.
import tkinter as tk
root=tk.Tk()
root.rowconfigure(0, weight=1)
root.rowconfigure(2, weight=1)
root.columnconfigure(0, weight=1)
root.columnconfigure(2, weight=1)
center_frame = tk.Frame(root)
center_frame.grid(row=1, column=1, sticky='nsew')
tk.Label(center_frame, text='Name/ID').grid(row=0, column=0)
tk.Label(center_frame, text='Password').grid(row=1, column=0)
tk.Button(center_frame, text='Enter').grid(row=2, column=1)
root.mainloop()
Here is an example using pack()
. I find grid()
to be my go to but pack()
can be used to accomplish much as well.
import tkinter as tk
root=tk.Tk()
center_frame = tk.Frame(root)
center_frame.pack(expand=True)
tk.Label(center_frame, text='Name/ID').pack(side='top')
tk.Label(center_frame, text='Password').pack(side='top')
tk.Button(center_frame, text='Enter').pack(side='right')
root.mainloop()